这就是声明构造函数private和声明=delete之间的区别

Which is the difference between declaring a constructor private and =delete?

本文关键字:声明 之间 delete 区别 private 构造函数      更新时间:2023-10-16

例如,我想声明一个类,但我希望客户端不能使用复制构造函数(或复制赋值操作符)

下面两个都不允许使用复制构造函数:

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);
}

将其设为私有是"老"的做法。构造函数仍然存在,但它是私有的,并且只能从另一个类成员函数中调用。

= delete 删除构造函数。它不是由编译器生成的,它根本不存在。

所以最有可能,= delete是你想要的。(不过需要注意的是,并非所有编译器都支持这种语法,所以如果考虑可移植性…)

声明复制构造函数private仍然允许Track类的成员函数复制构造该类的实例,而删除它只是禁止复制构造该对象。

在c++ 11中,删除复制构造函数是表达类不可复制这一事实的正确方式(当然,除非您让Track的成员函数或Track的友元函数复制构造Track对象)。

将构造函数设为私有基本上是旧c++中的一个"hack",因为这是阻止用户使用它们的唯一方法。delete特殊成员函数的功能仅在c++ 11中引入,这是表示类不可复制的更好、更惯用的方式。由于意图是明确的

私有构造函数除了完全禁止使用之外还有其他用途(例如,它们可以被静态类成员函数调用)。因此,仅仅将构造函数设为私有并不能很好地传达意图,并且产生的错误也不是很清楚。

您的第一个解决方案向读者传达了复制构造函数是私有的,不能使用。第二个解决方案只在c++ 11中有效。正因为如此,我认为更易于移植和可读的实现将是您的第一个,使用私有属性。

在第一种情况下,您实质上是声明一个私有复制构造函数,然后不提供任何实现。通过将它们声明为private,非成员就不能复制它。

在第二种情况下,语法禁止复制。这是c++原生的。

对于程序员来说,主要的区别在于可读性和对代码的理解。第一种情况是多余的,为什么要声明复制构造函数,使其私有,而不实现它。客户端必须在这里推断很多。

你可以直接使用"= delete",并清楚地表明你想要做什么

第一种方法并不能阻止类自身复制自身。解决这个问题的传统方法是将复制构造函数声明为private ,使其不被实现。

然而,这样做的一个问题是意图可能不明显。阅读代码的人可能不理解为什么存在孤立声明,并可能错误地删除它。注释可以提供帮助,如果Boost对您可用,则可以私下继承boost::noncopyable

第二种方法使意图明显,如果您可以使用c++ 11,则应该更喜欢这种方法。

如果使用c++ 11,请使用delete。原因是它使调用显式和意图清晰。你仍然可以意外地使用私有构造函数(例如,在一组受限的作用域中),但编译器将禁止你使用已删除的构造函数。

私有构造函数的一个问题是类和友元仍然可以使用它——这不会导致访问错误,而是导致链接错误,这些错误很难追溯到调用站点。

如果你的必要的工具链不支持删除的构造函数(= delete),你不应该定义它(如在你的问题中看到的)——只有声明它,并保持它未定义,例如:private: n Track(const Track&);