这是我的课程
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
答案 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};