对C ++构造函数删除感到困惑

时间:2020-07-27 01:42:16

标签: c++ constructor initialization copy-initialization

这是我的课程

class A {
public:
    A(int);
    A(A const&) = delete;
    A& operator=(const A& a) = delete;
// etc.
};

在另一个文件中,我可以这样调用构造函数:

auto foo = A(123);

解析为副本构造函数,而不是我期望的副本构造函数,为什么?

error C2280: 'mynamspace::A::A(const mynamespace::A &)': attempting to reference a deleted function

1 个答案:

答案 0 :(得分:6)

auto foo = A(123);执行copy initialization,从概念上讲,A(123)首先由A构造一个临时A::A(int),然后从foo复制初始化复制构造函数的临时属性(PS A没有移动构造函数)。在C ++ 17之前,该代码格式错误,因为复制构造函数被标记为delete

自C ++ 17起,mandatory copy elision完全消除了复制结构,并且代码格式正确。

(自C ++ 17起)首先,如果T是一个类类型,并且初始化程序是一个cv不合格类型与T属于同一类的prvalue表达式,则初始化程序表达式本身,而不是从中实现的临时对象,它用于初始化目标对象:请参见copy elision

(emphais矿山)

(从C ++ 17开始)在以下情况下,即使复制/移动构造函数和析构函数具有明显的副作用,也要求编译器忽略类对象的复制和移动构造。这些对象直接构造到存储中,否则会将它们复制/移动到其中。 复制/移动构造函数不需要存在或不可访问

请注意,在C ++ 17之前,复制省略是一种优化,即使可能执行,复制/移动构造函数仍然必须存在并且可以访问。

这是一种优化:即使发生并且未调用copy /move (since C++11)构造函数,它仍然必须存在并且可以访问(好像根本没有优化发生),否则程序格式错误。 :

您可以升级编译器以支持C ++ 17,或使用direct initialization(以消除使用复制构造函数的要求)。

A foo(123);
A foo{123};