我最近开始添加新的noexcept
规范,以尽可能地移动构造函数/赋值。现在我开始想知道隐式生成的成员函数的异常规范是什么样的。由于具有noexcept
移动函数允许使用更有效的代码路径(例如,在调整vector
时),我希望尽可能将它们声明为noexcept。我在理解标准对此有何看法时遇到了问题,因此尝试使用g ++ 4.6中的以下代码(使用-std=c++0x
)来掌握它:
struct foobar{};
int main()
{
foobar a, b;
std::cout<<std::boolalpha
<<noexcept(foobar())<<", "<<noexcept(foobar(a))<<", "
<<noexcept(a = b) <<", "<<noexcept(a = std::move(b))<<", "
<<noexcept(foobar(std::move(a)))<<std::endl;
}
这给了我一个True, True, True, False, False
的输出,意思是默认和复制构造函数/赋值noexcept
,而移动操作不在哪里。
现在我的问题:
在什么情况下隐式生成(或默认)成员函数声明为noexcept
?此外,foobar
正确或仅仅是gcc4.6中的编译器错误的行为是否存在?
答案 0 :(得分:18)
库错误 - 它在gcc 4.7中显示true, true, true, true, true
。
错误是不生成的移动构造函数不是noexcept,但std::move
未标记为noexcept
,我们可以通过其他测试看到:
std::cout << noexcept(a = static_cast<foobar&&>(b)) << ", " // true
<< noexcept(foobar(static_cast<foobar&&>(b))) << ", " // true
<< noexcept(std::move(b)) << std::endl; // false
gcc 4.6中的大多数库函数都不是noexcept-correct,这已在gcc 4.7中解决,
至于无限制生成的成员函数是不存在的,这在§15.4/ 14中有记载。基本上,如果它需要调用的所有函数都是noexcept
,则为noexcept
。
隐式声明的特殊成员函数(第12条)应具有异常规范。如果是
f
隐式声明的默认构造函数,复制构造函数,移动构造函数,析构函数,复制赋值 运算符或移动赋值运算符,其隐式异常 - 规范指定 type-idT
当且仅当 如果由T
的隐式定义直接调用的函数的 exception-specification 允许f
;f
应该 允许所有异常,如果它直接调用的任何函数允许所有异常,和f
将不允许异常 如果它直接调用的每个函数都不允许例外。