声明构造函数私有和 =delete 有啥区别?
Posted
技术标签:
【中文标题】声明构造函数私有和 =delete 有啥区别?【英文标题】:Which is the difference between declaring a constructor private and =delete?声明构造函数私有和 =delete 有什么区别? 【发布时间】:2013-05-21 10:16:41 【问题描述】:例如,我想声明一个类,但我希望客户端不能使用复制构造函数(或复制赋值运算符)
以下两种都不允许使用拷贝构造函数:
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);
【问题讨论】:
这是否编译Track(const Track&)=delete;
???
@EdHeal 是的,确实如此。 g++ 4.7
之前没见过delete
这样的用法。语言扩展?如果是,那么肯定比第一个“更正确”
delete
变体是 C++11,其意图很明确。就其他技术差异而言,您真的如此吗? (它可能涉及 C++ 标准的一些相当困难的部分,这可能对您的应用程序没有影响)。
这不是一个“真实”的代码,只是为了让我们说学术原因,我想知道是否有任何副作用或更多使用的。
【参考方案1】:
将其设为私有是“旧”的做法。构造函数仍然存在,但它是私有的,只能从另一个类成员函数中调用。
= delete
删除构造函数。它不是编译器生成的,根本就不存在。
所以很可能,= delete
就是您想要的。 (尽管需要注意的是并非所有编译器都支持这种语法,所以如果可移植性是一个问题......)
【讨论】:
【参考方案2】:声明复制构造函数private
仍然允许Track
类的成员函数复制构造该类的实例,而将其删除只是禁止复制构造该对象。
在 C++11 中,删除复制构造函数是表达类不可复制这一事实的正确方式(当然,除非让 @ 的成员函数有意义987654323@,或Track
的朋友,复制构造Track
对象)。
【讨论】:
【参考方案3】:将构造函数设为私有基本上是旧 C++ 中的“黑客”,因为这是阻止用户使用它们的唯一方法。 delete
特殊成员函数的能力只在 C++11 中引入,这是说一个类不能被复制的更好和更惯用的方式。因为它是明确的意图。
除了完全禁止使用之外,私有构造函数还有其他用途(例如,它们可能被静态类成员函数调用)。所以仅仅将构造函数设为私有并不能很好地传达意图,并且由此产生的错误也不是很清楚。
【讨论】:
【参考方案4】:您的第一个解决方案向读者传达了复制构造函数是私有的并且不能被使用。 您的第二个解决方案仅在 C++11 中有效。正因为如此,我想说更便携和可读的实现将是你的第一个,使用私有属性。
【讨论】:
【参考方案5】:在第一种情况下,您实际上是在声明一个私有复制构造函数,然后不提供任何实现。通过将它们声明为私有,非成员无法复制它。
在第二种情况下,语法禁止复制。这是 C++ 原生的。
作为程序员的主要区别在于可读性和对代码的理解。第一种情况是多余的,为什么要声明复制构造函数,使其私有,而不是实现它。客户必须在这里推断很多。
您可以只使用“= delete”并清楚地暗示您要做什么。
【讨论】:
【参考方案6】:您的第一种方法不会阻止类本身复制自身。解决此问题的传统方法是将复制构造函数声明为私有 并且 使其未实现。
然而,这样做的一个问题是意图可能并不明显。阅读代码的人可能不明白为什么存在孤立声明并可能错误地将其删除。如果 Boost 可供您使用,评论会有所帮助,就像从 boost::noncopyable
私下继承一样。
第二种方法使意图显而易见,如果您可以使用 C++11,您应该更喜欢这种方法。
【讨论】:
【参考方案7】:如果您使用 C++11,请使用 delete
。原因是它使调用明确且意图明确。您仍然可能不小心使用了私有构造函数(例如,在一组受限制的范围内),但编译器会禁止您使用已删除的构造函数。
私有构造函数的一个问题是类和朋友仍然可以使用它——这不会导致访问错误,而是 link 错误,这很难追溯到调用站点。
如果您的必要工具链不支持已删除的构造函数 (= delete
),则不应定义它(如您的问题所示)- 只需 声明 它并使其未定义,例如:@ 987654323@
【讨论】:
以上是关于声明构造函数私有和 =delete 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
请问把基类构造函数声明为protected有啥好处呢(抽象基类)