有时需要禁止C ++类中的复制构造函数,以便该类变为“不可复制”。当然,operator=
应该同时被禁止。
到目前为止,我已经看到了两种方法。方法1是将方法声明为私有,并且不给它实现:
class Class {
//useful stuff, then
private:
Class( const Class& ); //not implemented anywhere
void operator=( const Class& ); //not implemented anywhere
};
方法2是将方法声明为private并将其赋予“空”实现:
class Class {
//useful stuff, then
private:
Class( const Class& ) {}
void operator=( const Class& ) {}
};
IMO第一个更好 - 即使有一些意外的原因导致从同一个类成员函数调用复制构造函数,稍后会出现链接器错误。在第二种情况下,这个场景在运行时才会被忽视。
第一种方法有任何严重的缺点吗?什么是更好的方式,如果有的和为什么?
答案 0 :(得分:27)
第一个更好
class Class {
// useful stuff, then
public:
Class(const Class&) = delete;
void operator=(const Class&) = delete;
};
答案 1 :(得分:16)
第一种方法是Boost如何解决它(source code),据我所知,没有任何缺点。实际上,链接器错误是该方法的一大优势。您希望错误发生在链接时,而不是在客户端执行代码时它会突然崩溃。
如果你正在使用Boost,你可以节省一些打字。这跟你的第一个例子一样:
#include <boost/utility.hpp>
class Class : boost::noncopyable {
// Stuff here
}
答案 2 :(得分:7)
您始终可以从boost::noncopyable
继承。
否则我从未见过数字2优于数字1的原因,因为它允许你在朋友或类方法中“复制构造”一个对象,即使它实际上不会创建对象的真实副本。
答案 3 :(得分:3)
由于其他答案提出了其他建议,并没有真正尝试回答这个问题,所以这是我的尝试:
那么哪种方法更好?这取决于你如何定义禁止复制?
如果你想阻止其他人(只有非朋友的类和功能)复制,同时允许朋友和成员函数进行复制,那么第二种方法就是可行的方法。
如果您想阻止所有人(朋友,非朋友,会员功能)进行复制,那么第一种方法是唯一正确的解决方案。
请注意,第二种方法不会阻止朋友和成员函数复制(即调用复制函数)。 1
1。如果你没有在第二种情况下正确定义它们,那么复制将无法正常工作,但这完全是另一回事。但重点是第二种情况并不妨碍调用复制函数。编译器不会生成任何错误消息。
答案 4 :(得分:2)
你的第一种方法没有任何缺点,我一直用它来制作“不可复制”的课程。
答案 5 :(得分:1)
我个人认为你已经回答了自己的问题,应该使用第一种方法。
如果您不希望它完全可复制,正如您所说,它将引发链接器错误。但是,如果您使用第二种方法,并且您最终意外地使用了复制构造函数,它将进行编译并且将运行;在你打开调试器之前,你绝对没有迹象表明不一致的地方。或者如上所述,如果您可以使用现代编译器,请使用C ++ 11的'= delete'表示法。