例如,我想声明一个类,但我希望客户端无法使用复制构造函数(或复制赋值运算符)
以下两个都不允许使用复制构造函数:
1
class Track
{
public:
Track(){};
~Track(){};
private:
Track(const Track&){};
};
2
class Track
{
public:
Track(){};
~Track(){};
Track(const Track&)=delete;
};
其中一种方式“比其他方式更正确”还是相同?有副作用吗?
//Does not compile with both the above ways
int main()
{
Track l;
Track p(l);
}
答案 0 :(得分:15)
将其设为私有是实现这一目标的“旧”方式。构造函数仍然存在,但它是私有的,只能从另一个类成员函数中调用。
= delete
删除构造函数。它不是由编译器生成的,它根本就不存在。
所以最有可能的是,= delete
就是你想要的。 (尽管有一点需要注意,并非所有编译器都支持这种语法,所以如果可移植性是一个问题......)
答案 1 :(得分:8)
声明复制构造函数private
仍然允许Track
类的成员函数复制构造该类的实例,同时删除它只是禁止复制构造该对象。
在C ++ 11中,删除复制构造函数是表达类不可复制的正确方法的正确方法(当然,除非你让{}的成员函数有意义。 {1}}或Track
的朋友,复制 - 构建Track
个对象。)
答案 2 :(得分:5)
使构造函数私有在旧C ++中基本上是“黑客”,因为它是防止用户使用它们的唯一方法。 delete
特殊成员函数的功能仅在C ++ 11中引入,并且它是更好,更惯用的方式来表示无法复制类。因为它明确关于意图。
私有构造函数除了完全禁止使用之外还有其他用途(例如,它们可以由静态类成员函数调用)。所以只是将构造函数设为私有并不能很好地传达意图,结果错误也不是很清楚。
答案 3 :(得分:0)
您的第一种方法并不会阻止类本身复制自身。解决此问题的传统方法是声明copy-constructor private 和以使其未实现。
然而,问题在于意图可能并不明显。阅读代码的人可能不理解为什么存在孤立声明并且可能会错误地将其删除。评论可以提供帮助,如果您可以使用Boost,则可以私下继承boost::noncopyable
。
第二种方法使意图显而易见,如果你可以使用C ++ 11,你应该更喜欢它。
答案 4 :(得分:0)
您的第一个解决方案向读者传达了复制构造函数是私有的,不会被使用。 您的第二个解决方案仅在C ++ 11中有效。因此,我会说使用私有属性的第一个便携式和可读性更强的实现。
答案 5 :(得分:0)
如果您使用的是C ++ 11,请使用delete
。原因是它使调用明确,意图明确。您仍然可能会意外地使用私有构造函数(例如,在一组受限制的范围内),但编译器将禁止您使用已删除的构造函数。
私有构造函数的一个问题是类和朋友仍然可以使用它 - 这不会导致访问错误,而是链接错误,这可能很难追溯到调用点。< / p>
如果您的必要工具链不支持已删除的构造函数(= delete
),则不应定义它(如您的问题所示) - 只有声明并保持未定义,例如:private: \n Track(const Track&);
答案 6 :(得分:0)
在第一种情况下,您基本上声明了一个私有拷贝构造函数,然后没有提供任何实现。通过将它们声明为私有,非成员无法复制它。
在第二种情况下,语法禁止进行复制。这是C ++原生的。
作为程序员的主要区别在于可读性和理解代码。第一种情况是多余的,为什么声明复制构造函数,使其成为私有,而不是实现它。客户必须在这里推断很多。
您可以使用“=删除”并明确暗示您要做的事情。