7

在 C++ 中,如果我定义了一个复制构造函数和 operator= 对类进行非常量引用,编译器是否应该仍然为 const 引用提供默认版本?

struct Test {
  Test(Test &rhs);
  Test &operator=(Test &rhs);

private:
  // Do I still need to declare these to avoid automatic definitions?
  Test(const Test &rhs);
  Test &operator=(const Test &rhs);
};
4

2 回答 2

7

不,如果您定义了复制构造函数和赋值运算符,编译器将不会隐式声明或定义它自己的。请注意,copy-constructor的定义允许参数由 const 或非 const 引用采用,因此您的构造函数确实是一个copy-constructor。同样对于operator=

[省略了很大一部分细节,特别是在什么情况下隐式声明的特殊成员函数也会被隐式定义]

12.8 [class.copy]/2 类 X 的非模板构造函数是复制构造函数,如果它的第一个参数是 X&、const X&、volatile X& 或 const volatile X& 类型,并且要么没有其他参数,要么所有其他参数参数具有默认参数 (8.3.6)。

12.8 [class.copy]/7 如果类定义没有显式声明复制构造函数,则隐式声明。

12.8 [class.copy]/17 用户声明的复制赋值运算符 X::operator= 是类 X 的非静态非模板成员函数,只有一个 X、X&、const X&、volatile X& 或 const 类型的参数挥发性X&。

12.8 [class.copy]/18 如果类定义没有显式声明复制赋值运算符,则隐式声明一个。

于 2012-08-13T14:50:41.640 回答
1

不,一旦您声明了自己的复制构造函数或复制赋值运算符(无论它是否使用规范const性),编译器将不再为您执行此操作。

但是通过非常量引用来做到这一点几乎是违反最小意外原则的教科书示例。每个人都希望可以分配 const 对象,并且右侧不会发生变异。第一个并没有那么糟糕,因为编译器会捕捉到它,但第二个可能会导致各种难以发现的错误。

如果您尝试实现移动语义并且不能使用 C++11,我建议创建一个特殊的移动方法,并且根本不允许“移动”构造。如果您可以使用 C++11,则使用内置的右值引用。

于 2012-08-13T14:59:07.100 回答