删除复制构造器和复制分配 - public,私有的还是受保护的?

Deletion of copy-ctor & copy-assignment - public, private or protected?

为了使对象不可复制,我们可以显式删除其复制构造函数和复制赋值运算符。

我的问题是:在 publicprivateprotected 部分的 class 部分,什么是正确的地方?而且 - 这个选择有什么不同吗?

deleted 函数的访问无关紧要。事实上,对于 class 成员,添加额外的访问说明符 (delete:) 会更有意义。我怀疑他们没有这样做的原因是它不适用于 non-member 函数。

对于复制构造函数之类的东西,从文体上讲,将其放在 public 部分更有意义。 class 没有复制构造函数这一事实是了解 class.

接口的一个非常重要的事实。

对于声明特定重载已删除以便 compiler-time 检测到错误的内部函数,将函数声明在与所有其他重载相同的部分中是有意义的。

deleteprivate 访问一样有效。

delete的作用是如果通过重载决议选择函数会导致错误。

private 的作用是,如果函数是通过 class 或其朋友之外的重载决议选择的,则会导致错误。

如果这两个错误都适用,则最终结果是相同的,但 public 可能有助于避免有关访问权限的编译器消息,这可能会导致混淆。

Does where we put the deleted definition make any difference?

从纯语言的角度来看,它绝对是零差异。名称查找和重载解析发生在访问检查之前。并试图在重载决议结束时引用已删除的函数会使您的程序 ill-formed,句点。编译器可能会也可能不会发出有关可访问性的另一个诊断,但程序已经有一个必须报告的错误。

因此,您可以将已删除的定义放入您想要的任何可访问性中。我认为大多数人会将其保密,以符合 class non-copyable 的 "old" 做法(将这些成员的声明放在 class 的私有部分, 而不是定义它们), 如果只是为了帮助那些更快地了解旧方法的人 "get it" 。混合成语,如果你愿意的话。

如果您需要同时支持 C++03 和 C++11 模式,那么标记为私有也是您无法避免的事情。在宏的帮助下,可以轻松地使 header 符合两个标准:

#if __cplusplus >= 201103L
  #define DELETED_DEFINITION = delete
#else
  #define DELETED_DEFINITION
#endif

class noncopyable {
private:
  // This header can be compiled as both C++11 and C++03
  noncopyable(noncopyable const&) DELETED_DEFINITION;
  void operator=(noncopyable const&) DELETED_DEFINITION;
};

what is the right place to do it - in the public, private or protected section of the class?

我会将它们放在public部分

这是因为删除构造函数或赋值运算符与创建它们正交 private / protected;如果不删除这些,则默认为 public。在我看来,将删除内容放在这两个部分之一中似乎是在暗示 "If I hadn't deleted them, I would have made them private/protected" - 这不是您想在您的案例中传达的信息。

不过请注意,编译器并不关心您将删除放在哪个部分。

从 Scott Meyers 的书 Effective Modern C++(第 10 项)看来,将它们定义为 public 似乎更好:

By convention, deleted functions are declared public, not private. There’s a reason for that. When client code tries to use a member function, C++ checks accessibility before deleted status. When client code tries to use a deleted private function, some compilers complain only about the function being private, even though the function’s accessibility doesn’t really affect whether it can be used. It’s worth bearing this in mind when revising legacy code to replace private-and-not-defined member functions with deleted ones, because making the new functions public will generally result in better error messages.

此外,我认为删除的副本 constructor/assignment 应该是 class 界面的一部分,以便与所有 class 用户共享。此类信息不应通过保密来保密。