标准(5.2.2 函数调用 [expr.call] §4)规定参数初始化和销毁发生在调用函数的上下文中。所以是的,它is从技术上讲是洁净的声明f
as noexcept
.
尽管一开始是违反直觉的,但它确实有道理。f
可以使用右值调用,在这种情况下,将使用 move-ctor 来初始化参数,因此即使调用函数的整个构造(包括参数设置和拆卸)仍然会是noexcept
. Or f
可以用空向量调用,在这种情况下,整个构造仍然会有效地 be noexcept
- 至少是我认为“合理”的库实现。
还要考虑带有 const-ref 参数的函数:
void x(std::string const&) noexcept {}
void y() noexcept
{
x("foo");
}
x
is noexcept
好的。来电y
然而不是,因为它包含一个(可能抛出)隐式转换。所以如果声明f
as noexcept
风格很糟糕,难道不应该这样说吗x
?
所以我认为C++程序员应该做两件事之一:不使用和不依赖noexcept
规范,或内化规则,并始终对他们在呼叫站点所做的事情感到厌倦。
关于第二个问题(强保证)...
我想说一个函数永远不能声明论点它被称为与。而且它永远不能对它的未来发生的事情做出声明参数如果它从未被真正调用过。
如果您心目中的强有力的保证包括此类声明,那么我同意该功能不能提供这种强有力的保证。
尽管我不一定同意强有力的保证——对于具有这样的签名的函数——应该包括这样的声明。
我什么would说的是:if这种声明对于强有力的保证具有任何实际意义是必要的,那么该函数不应该使用按值参数。
OTOH,如果这样的主张对于强有力的保证具有实际意义来说不是必要的,那么我认为我没有理由“禁止”它。例如。
void StrongAppendAll(std::vector<T>& a, std::vector<T> b);
IMO对该功能的“自然”有力保证是它要么附加所有元素b
to a
,或者,如果抛出异常,则离开a
不变。我绝不会假设该保证包括任何有关所发生情况的索赔b
。更不用说关于用于初始化的任何参数会发生什么的任何声明b
.