【发布时间】:2021-08-09 03:38:42
【问题描述】:
自 C++17 以来,prvalue 的含义发生了变化,这使得在某些情况下可以保证复制省略。从 cppreference 开始,复制/移动构造函数在这种情况下不需要存在或可访问。
当抛出异常时,异常对象被复制初始化,复制/移动可能会受到复制省略。但是否要求此时复制/移动构造函数必须可用?
当抛出的对象是类对象时,为复制初始化选择的构造函数以及考虑抛出的对象为左值的复制初始化选择的构造函数应该是不可删除和可访问的,即使如果复制/移动操作被省略 ([class.copy.elision])。析构函数可能被调用([class.dtor])。
标准中提到相应的构造函数必须是不可删除且可访问的,即使它被省略了。
但是我测试发现GCC和Clang都允许在删除对应的构造函数时抛出:
struct A {
A() = default;
A(A&&) = delete;
};
try {
throw A{}; // copy elision
} catch(...) {}
代码可以编译,但似乎不符合标准的要求。如果我将版本从 C++17 降低到 C++14,它们都会报错:
struct A {
A() = default;
A(A&&) = delete;
};
try {
throw A{}; // error: call to deleted constructor of 'A'
} catch(...) {}
是我对标准的理解有误,还是只是编译器放宽了限制?
【问题讨论】:
标签: c++ c++17 language-lawyer