据我所知,我可以通过定义私有的复制构造函数和赋值操作符来“禁止”复制和赋值给我的对象:
class MyClass
{
private:
MyClass(const MyClass& srcMyClass);
MyClass& operator=(const MyClass& srcMyClass);
}但是这有什么用呢?
这被认为是一种糟糕的做法吗?
如果你能描述一下这种情况,我将不胜感激,在这种情况下,以这种方式“禁用”赋值和复制构造函数是合理的/有用的。
发布于 2012-01-30 04:10:19
当复制对象没有意义时,它很有用。这绝对不被认为是一种糟糕的做法。
例如,如果您有一个表示网络连接的类,那么复制该对象就没有意义。另一种情况是,如果你有一个类代表多人游戏中的一个玩家,那么你可能希望一个类是不可复制的。这两个类都表示不能在现实世界中复制的东西,或者复制没有意义的东西(一个人,一个连接)。
此外,如果您正在尝试实现Singleton,则将对象设置为不可复制是标准过程。
发布于 2012-01-30 06:22:24
一般来说,任何管理资源的类都应该是不可复制的,或者具有专门的复制语义。反之亦然:任何不可复制或需要专门复制语义的类都是在管理资源。实际上,在C++语言中,“管理资源”的意思是负责内存中的一些空间,或者负责到网络或数据库的连接,或者到文件的句柄,或者撤消事务,等等。
资源管理捕获了相当多的示例。这些责任需要一个前缀操作,一个后缀操作,以及可能在两者之间的一些操作。例如,内存管理涉及到获取内存地址的句柄,我们将对其进行管理,可能会摆弄该内存,最后释放该句柄(因为如果你喜欢某件东西,就让它自由)。
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类几乎是正确的:它自动获取底层内存空间并自动释放它,即使异常在它获得其资源一段时间后传播。但是考虑一下这个场景:
{
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++中,复制对象而不引起注意是非常容易的:一个函数通过值获取参数,通过值返回参数,或者通过引用获取参数,然后调用另一个函数,该函数本身通过值获取(或返回)参数……更容易假设的是,所有东西都会被复制。
所有这些都表明,当一个类“存在的理由”正在管理一个资源时,你应该立即知道你需要处理复制。你应该决定
到目前为止,我会说资源管理是禁用复制或提供专门的复制语义的唯一情况。这只是对The Rule of Three的另一种看法。
发布于 2012-01-30 04:10:45
这是一种非常普遍的做法。有很多不适合复制的例子。
假设您的对象表示一个开放的服务器端套接字(即传入的网络连接);复制该对象的语义是什么?
https://stackoverflow.com/questions/9056305
复制相似问题