首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >禁止赋值和传值

禁止赋值和传值
EN

Stack Overflow用户
提问于 2012-01-30 04:06:32
回答 5查看 4.2K关注 0票数 11

据我所知,我可以通过定义私有的复制构造函数和赋值操作符来“禁止”复制和赋值给我的对象:

代码语言:javascript
复制
class MyClass
{
private:
    MyClass(const MyClass& srcMyClass);
    MyClass& operator=(const MyClass& srcMyClass);
}

但是这有什么用呢?

这被认为是一种糟糕的做法吗?

如果你能描述一下这种情况,我将不胜感激,在这种情况下,以这种方式“禁用”赋值和复制构造函数是合理的/有用的。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-01-30 04:10:19

当复制对象没有意义时,它很有用。这绝对不被认为是一种糟糕的做法。

例如,如果您有一个表示网络连接的类,那么复制该对象就没有意义。另一种情况是,如果你有一个类代表多人游戏中的一个玩家,那么你可能希望一个类是不可复制的。这两个类都表示不能在现实世界中复制的东西,或者复制没有意义的东西(一个人,一个连接)。

此外,如果您正在尝试实现Singleton,则将对象设置为不可复制是标准过程。

票数 11
EN

Stack Overflow用户

发布于 2012-01-30 06:22:24

一般来说,任何管理资源的类都应该是不可复制的,或者具有专门的复制语义。反之亦然:任何不可复制或需要专门复制语义的类都是在管理资源。实际上,在C++语言中,“管理资源”的意思是负责内存中的一些空间,或者负责到网络或数据库的连接,或者到文件的句柄,或者撤消事务,等等。

资源管理捕获了相当多的示例。这些责任需要一个前缀操作,一个后缀操作,以及可能在两者之间的一些操作。例如,内存管理涉及到获取内存地址的句柄,我们将对其进行管理,可能会摆弄该内存,最后释放该句柄(因为如果你喜欢某件东西,就让它自由)。

代码语言:javascript
复制
template<typename T>
struct memory {
    memory(T const& val = T()) : p(new T(val)) { } 
    ~memory() { delete p }
    T& operator*() const { return *p; }
private:
    T* p;
};

// ...
{
    memory<int> m0;
    *m0 = 3;
    std::cout << *m0 << '\n';
}

这个memory类几乎是正确的:它自动获取底层内存空间并自动释放它,即使异常在它获得其资源一段时间后传播。但是考虑一下这个场景:

代码语言:javascript
复制
{
    memory<double> m1(3.14);
    memory<double> m2(m1);  // m2.p == m1.p (do you hear the bomb ticking?)
}

因为我们没有为memory提供专门的复制语义,所以编译器提供了自己的复制构造函数和复制赋值。它们做了错误的事情:m2 = m1表示m2.p = m1.p,这样两个指针指向相同的地址。这是错误的,因为当m2超出作用域时,它会像一个好的负责任的对象一样释放它的资源,而当m1又超出作用域时,它也释放了它的资源,m2已经释放了相同的资源,完成了一个双重删除--一个臭名昭著的未定义行为场景。此外,在C++中,复制对象而不引起注意是非常容易的:一个函数通过值获取参数,通过值返回参数,或者通过引用获取参数,然后调用另一个函数,该函数本身通过值获取(或返回)参数……更容易假设的是,所有东西都会被复制。

所有这些都表明,当一个类“存在的理由”正在管理一个资源时,你应该立即知道你需要处理复制。你应该决定

  • 你支持复制,而你决定复制意味着什么:安全地共享资源,执行底层资源的深度复制以便没有任何共享,或者像copy-on-write或惰性复制那样组合这两种方法。无论选择哪种路径,您都需要提供专门的复制构造函数和复制赋值运算符
  • 或您不支持任何类型的资源复制,在这种情况下,您需要禁用复制构造函数和复制赋值运算符。

到目前为止,我会说资源管理是禁用复制或提供专门的复制语义的唯一情况。这只是对The Rule of Three的另一种看法。

票数 5
EN

Stack Overflow用户

发布于 2012-01-30 04:10:45

这是一种非常普遍的做法。有很多不适合复制的例子。

假设您的对象表示一个开放的服务器端套接字(即传入的网络连接);复制该对象的语义是什么?

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9056305

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档