我创建了一个类Animal
:
class Animal {
public:
Animal() = default;
Animal(Animal&& a) = delete;
Animal(Animal& a) = delete;
Animal& operator=(Animal&& a) = delete;
Animal& operator=(Animal& a) = delete;
};
Animal func1() {
return Animal();
}
Animal func2() {
Animal a {};
return a;
}
int main(void) {
Animal a1 = func1();
Animal a2 = func2();
return 0;
}
我不明白为什么func1()
可以正常工作:return Animal()
创建一个右值对象并a1
在函数中使用该对象进行初始化main
;如我所见,它等于
Animal a1 = func1()
==
Animal a1 = Animal&& temp //(I wrote type in assignment for clarifying)
我已经读过返回值是一个右值;但是,在func2
我得到一个错误,“复制构造函数被删除”而不是移动构造函数,为什么?
在这里,我们考虑以下声明:
Animal a1 = func1();
调用表达式func1()
是一个rv类型的值Animal
。从 C++17 开始,由于强制复制 elison:
在以下情况下,编译器必须省略类对象的复制和移动构造,即使复制/移动构造函数和析构函数具有可观察到的副作用。对象直接构建到存储中,否则它们将被复制/移动到。复制/移动构造函数不需要存在或可访问:
- 在 return 语句中,当操作数是与函数返回类型相同的类类型(忽略 cv 限定)的纯右值时:
也就是说,对象直接构建到存储中,否则它们将被复制/移动到。也就是说,在这种情况下(对于 C++17),不需要可用的复制/移动构造函数。所以这个声明有效。
在这里,我们考虑以下声明:
Animal a2 = func2();
这里来自非强制性复制 elison,
在以下情况下,编译器允许但不需要省略类对象的复制和移动(C++11 起)构造,即使复制/移动(C++11 起)构造函数和析构函数具有可观察的一面-效果。对象直接构建到存储中,否则它们将被复制/移动到。这是一种优化:即使它发生并且没有调用复制/移动(自 C++11 起)构造函数,它仍然必须存在且可访问(就好像根本没有发生任何优化一样),否则程序会出错 -形成:
- 在 return 语句中,当操作数是具有自动存储持续时间的非易失性对象的名称时,它不是函数参数或 catch 子句参数,并且属于相同的类类型(忽略 cv 限定)函数返回类型。
也就是说,复制/移动构造函数必须存在(即这些 ctor 必须存在且可访问),但由于您已明确将它们标记为已删除,因此此语句失败并出现错误:
error: use of deleted function ‘Animal::Animal(Animal&&)’
错误也可以在这里看到
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句