我理解如果复制ctor在类中被声明为私有,编译器将不会生成默认复制ctor。
但有人可以解释为什么编译器会这样做吗?
如果复制ctor被声明受保护会怎样?编译器会提供默认的复制ctor吗?
如果复制ctor被声明为私有但有一个定义,例如,会发生什么? foo(const& obj){}
答案 0 :(得分:5)
在类中声明的任何复制构造函数(无论是私有的,公共的还是受保护的)都意味着编译器不会生成默认的复制ctor。那么在类中声明的那个是否也被定义或者不仅仅控制具有适当级别的可见性的代码是否可以复制类的实例(如果没有定义,链接器将会抱怨;编译器的工作只是抱怨使用没有适当的可见性,不要复制链接器的工作。)
例如,如果声明私有副本ctor,则只有在尝试复制实例时,才允许编译类中的函数(或朋友,当然)。如果未定义ctor,那么该代码将无法在链接器中存活,因此无论如何都会出现错误(不幸的是,在构建过程中稍晚一点,也就是说,与早期版本相比,构建时可能会浪费大量的计算资源 - 检测到的错误)。
答案 1 :(得分:3)
编译器知道存在复制构造函数,因此它不会生成一个。在此阶段不考虑可访问性(公共/私有/受保护)或是否具有定义。
听起来没有复制构造函数只是因为你无法从外部和非朋友调用私有函数。用户定义的构造函数仍然存在,只是它是私有的。
如果它受到保护,那么只有子类本身可以调用复制构造函数。也没有隐式定义的拷贝构造函数。
答案 2 :(得分:2)
$ 12/1 - “默认构造函数 (12.1),复制构造函数和副本 赋值运算符(12.8),和 析构函数(12.4)是特殊成员 功能。 [注意:实施 将隐含声明这些成员 某些类类型的函数何时 该计划没有明确 宣布他们。实施将 隐含地定义它们,如果它们是 使用强> [...]“
因此,如果复制构造函数是显式声明的,编译器会将其视为具有自定义复制构造函数的意图,并且隐式复制构造函数生成被抑制。
可以声明复制构造函数并将其定义为私有。如果复制构造函数被定义为私有,则复制初始化/直接初始化将不起作用,如下所示。
struct A{
A(){}
private:
A(A const &){}
};
int main(){
A a1;
A a2(a1); // direct initialization, error
A a3 = a1; // copy initialization, error
}
答案 3 :(得分:1)
只要显式声明了复制构造函数,编译器就不会生成默认的复制构造函数。无论隐私声明具有什么隐私级别(私有,受保护或公开),都是如此。