何时可以在函数及其参数之间交错未序列的代码?

Chr*_*ter 0 c++ c++11

假设我有类型TU和函数U f(T)T g(),和我写的表达f(g()).在什么情况下,附近的未序列表达式中的代码可能在之后g但之前执行f

我理解一个情况是在函数调用中h(f(g()), j()),j可以在任何时候相对于g和执行f.这基本上是唯一的例子,还是其他的?

为动机,所述功能std::make_shared<T>std::make_unique<T>可用于写更多异常安全代码,如图的由不安全代码此示例http://herbsutter.com/gotw/_102/:

// In some header file:
void f( std::unique_ptr<T1>, std::unique_ptr<T2> );

// At some call site:
f( std::unique_ptr<T1>{ new T1 }, std::unique_ptr<T2>{ new T2 } );
Run Code Online (Sandbox Code Playgroud)

T2构造可以在后抛出异常T1构造函数,但在之前std::unique_ptr<T1>的构造,从而导致T1被泄露.解决方案是改为编写f( make_unique<T1>(), make_unique<T2>() );.

我发现的所有异常安全性的讨论都std::unique_ptr使用相同的例子.这让我想知道多参数函数中的参数表达式(包括像+和这样的某些运算符[])是否是预期此行为的唯一情况.

ric*_*ici 5

[intro.execution] (§1.9)包含规则,实际上非常简单.

14在与要评估的下一个完整表达式相关联的每个值计算和副作用之前,对与完整表达式相关联的每个值计算和副作用进行排序.

15除非另有说明,否则对单个算子的操作数和个别表达式的子表达式的评估是不确定的.

完整表达式就是它所说的:一个表达式,它不是任何其他表达式的子表达式.因此,只有表达式的子表达式才能被排除,而不是全部.例如,某些运算符对其参数的执行进行排序,并且函数调用是不确定地排序的(即,不是交错的).