【发布时间】:2021-09-03 03:21:01
【问题描述】:
我有以下代码。
#include <iostream>
struct Box {
Box() { std::cout << "constructed at " << this << '\n'; }
Box(Box const&) { puts("copy"); }
Box(Box &&) = delete;
~Box() { std::cout << "destructed at " << this << '\n'; }
};
auto f() {
Box v;
return v; // is it eligible for NVRO?
}
int main() {
auto v = f();
}
上面的代码产生错误。 call to deleted constructor/function in both gcc and clang
但如果我将代码更改为返回纯右值,代码就可以工作。
auto f() {
Box v;
return Box(); // is it because of copy elision?
}
为什么会这样?是因为删除移动构造函数吗? 如果我将复制和移动构造函数都更改为显式,它也会产生错误?
如果标记为已删除,为什么不能简单地使用定义的复制构造函数
编辑:
compiled with -std=c++20 in both gcc and clang, error.
compiled with -std=c++17 gcc, compiles.
compiled with -std=c++17 clang, error.
编辑 2:
clang version: 12.0.0
gcc version: 11.1
【问题讨论】:
-
Not reproducible。按预期使用 C++17。
-
较旧的编译器版本可以使用
-std=c++17很好地编译它,但较新的编译器版本会失败。这很奇怪。 -
@Zoso 删除的移动构造函数仅在自动标记为已删除(未声明,或使用
= default定义,并且不能是基类或非静态成员)时才被跳过已移动),而不是使用= delete声明的。 -
"如果标记为已删除,为什么不能简单地使用定义的复制构造函数" 当标记为
= delete时,移动构造函数仍然成为考虑的候选对象.这与编译器无法合成移动构造函数时不同,在这种情况下,它不会被视为候选者。我希望我可以做= void(或其他东西)来明确提供“我打算不生成这个”,而不会将它作为匹配考虑的候选者。唉,只能用评论代替。 -
@Zoso [over.match.funcs]/9 "A defaulted 将定义为已删除的特殊成员函数从所有上下文中的候选函数集中排除。"
标签: c++ c++17 c++14 c++20 copy-elision