【问题标题】:Accessing constructor with value initialization?使用值初始化访问构造函数?
【发布时间】:2018-09-25 19:01:04
【问题描述】:

所以根据this article,符号A()new A() 导致值初始化。我的理解是,这两种符号都应该转换为默认初始化

如果 T 是一个没有默认构造函数的类类型或 用户提供或删除的默认构造函数,对象为 默认初始化;

它们应该导致相同的行为。那么,为什么会这样:

class Image
{
public:
    Image();
    virtual ~Image();

protected:
    std::string _filePath;

protected:
    // noncopyable
    Image(const Image& rImg);
    Image& operator=(const Image&);
    bool initWithImageFileThreadSafe(const std::string& fullpath);

};

int main()
{
    auto a = new Image(); //Works
    auto aa = Image(); //Error: inaccessible constructor
}

【问题讨论】:

  • 按预期编译heremain 中的第二行需要 C++17 来实现 “保证省略”
  • 干净编译:直播godbolt.org/z/OdMGDQ 或许可以添加工具链和开关的详细信息。
  • C++14 live 失败:godbolt.org/z/wsVmt7 但您的 cmets 似乎已被交换。
  • 啊,C++17 的保证复制省略在这里发挥了作用。

标签: c++


【解决方案1】:

当你这样做时

auto a = new Image(); //Works

您动态创建一个Image,并使用指向它的指针初始化a。这很好,因为它是 Image 的直接初始化。

当你这样做时

auto aa = Image(); //Error: inaccessible constructor

在 C++17 之前,您调用复制初始化,它使用初始化临时值 Image 作为初始化 aa 的值。由于您的复制构造函数标记为protected,因此实际上不允许发生这种情况,并且您会收到编译器错误。即使可以省略此副本,您仍然需要一个可访问的复制/移动构造函数。

在 C++17 之后,此处实际上并没有生成临时代码,编译器实质上将代码转换为 Image aa{};,因此副本被忽略,并且不需要可访问的复制/移动构造函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-23
    • 1970-01-01
    • 2021-08-03
    • 2013-05-23
    • 2018-08-02
    • 1970-01-01
    相关资源
    最近更新 更多