为什么编译器在这个上烦我?

inf*_*ler 17 c++

(使用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)

  • 在优化之前抛出错误.它确实在逻辑上调用了复制构造函数. (4认同)
  • -1.`exampleClass e1();`声明一个名为`e1`的函数,它不带参数并返回`exampleClass`.使用默认构造函数构造对象的正确方法是:`exampleClass e1;`虽然答案的其余部分是正确的,但我取消了我的-1. (3认同)