(使用Visual C++ 2010,在调试中编译并关闭优化)
我有以下非常简单的课程:
class exampleClass
{
public:
exampleClass()
{
cout << "in the default ctor" << endl;
}
private:
exampleClass (const exampleClass& e)
{
cout << "in the copy ctor" << endl;
}
};
Run Code Online (Sandbox Code Playgroud)
当我尝试使用以下main编译它时:
#include <iostream>
using namespace std;
int main()
{
exampleClass e1=exampleClass();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我收到编译错误:
'exampleClass::exampleClass' : cannot access private
member declared in class 'exampleClass'
Run Code Online (Sandbox Code Playgroud)
当我从copy ctor中删除访问修饰符"private"时,程序仅编译并打印:
in the default ctor
Run Code Online (Sandbox Code Playgroud)
为什么会这样?如果编译器无论如何都不会调用copy ctor,为什么它会烦我?
由于有些人错过了第一行(至少在一些编辑之前),我将重复它:
小智 16
这种类型的初始化称为复制初始化.我相信C++ 11标准中的以下条款适用于此处(第8.5.16节,第204页):
如果初始化是直接初始化,或者它是复制初始化,其中源类型的cv-nonqualified版本与目标类相同的类或派生类,则考虑构造函数.列举了适用的构造函数(13.3.1.3),并通过重载解析(13.3)选择最佳构造函数.调用所选的构造函数来初始化对象,初始化表达式或表达式列表作为其参数.如果没有构造函数适用,或者重载决策是不明确的,则初始化是错误的.
在这种情况下,最适用的构造函数是copy ctor,它是私有的,因此是错误消息.
为了进一步回答您的问题,当复制版本是私有的时,由于标准规定的规则,您的程序根本不允许通过编译器检查.当您公开复制ctor时,程序将变为有效,但对复制程序的调用将被优化掉.
编辑:好的,详细说明上一段.你在这里处理所谓的复制省略.虽然在这种情况下可以复制省略,但标准要求您为班级提供可访问的复制文件.
orl*_*rlp 12
exampleClass e1=exampleClass();
Run Code Online (Sandbox Code Playgroud)
这将首先exampleClass使用默认构造函数创建临时,然后将其复制到e1使用复制构造函数.这将调用私有拷贝构造函数,从而给你错误.使用默认构造函数实例化类实例的正确方法是:
exampleClass e1;
Run Code Online (Sandbox Code Playgroud)