在f(x)中,x可以在f之前被评估吗?

我有一个C ++程序。 这个程序做这样的事情:

struct MyT {void memfunc(std::unique_ptr<MyT> arg);}; std::unique_ptr<MyT> obj = /* some init */; obj->memfunc(std::move(obj)); 

这是保证是有效的,或者我可以最终调用nullptr成员函数?
标准报价适用。
我知道参数的评估顺序是不确定的,但是我不记得顺序是如何调用函数对象的。

Pre-C ++ 17,这是未定义的行为:

这里的引用certificate了在函数调用之前,所有评估都需要调用一个函数和相关的副作用。
此外,所有其他未经特别sorting的评估都是不确定的。
这不会对所评估的子expression式施加任何sorting约束,但它们彼此之间仍然没有任何关系。

1.9程序执行§15

除了注意到的地方之外, 对个别操作符和个别expression式的操作数的评估是不确定的。
[…]
运算符操作数的值计算在运算符结果的值计算之前被sorting。 如果对标量对象的副作用不是相对于同一标量对象的其他副作用或者是使用相同标量对象的值进行值计算,则行为是未定义的。
当调用一个函数函数是否是内联函数)时,在任何参数expression式或者指定被调用函数的后缀expression式的每一个值计算和副作用在执行每个expression式或者语句称为function。
[注:与不同参数expression式相关的值计算和副作用是不确定的。 – 注意]
调用函数(包括其他函数调用)中的每个评估在执行被调用函数的主体之前或之后都没有特别的sorting,就被调用函数的执行而言是不确定地sorting的 .9 C ++中的几个上下文导致评估即使在翻译单元中没有出现相应的函数调用语法 。 […]
被调用函数执行的顺序约束(如上所述)是被调用的函数调用的特征,无论调用该函数的expression式的语法如何。

其他相关的引号是关于std::move

template typename remove_reference :: type && move(T && t)noexcept;
返回:static_cast <typename remove_reference :: type &&>(t)。

std::unique_ptr<T>.operator->()

20.7.1.2.4 unique_ptr观察者

指针运算符 – >()const noexcept;
需要:get()!= nullptr。
返回:get()。

memfunc通过值获取它的参数,所以我们有3个调用:
a) obj->memfunc b) std::move(obj)
c)传入参数的移动构造函数。
因为b)没有改变任何东西,所以我们可以忽略它:

a和c是不确定的,所以或者可以在另一个之前。
如果先发生,一切都很好,改变obj并不重要。
如果c首先发生,则用一个归零obj来评估a,违反前提条件,所以我们有UB。

总之,这是未定义的行为,因为其中一个允许的订单具有未定义的行为。

Post-C ++ 17,它是明确的:

8.2.2函数调用[expr.call]

1函数调用是后缀expression式,后面跟着圆括号,其中包含一个可能为空的逗号分隔的构成函数参数的初始化子句列表。 […]
[…]
5 后缀 expression式expression式列表中的每个expression式和任何默认参数之前被sorting。 […]
[…]

是的x的评价可以在评价f (它们是无序的 )之前,之后或期间发生。

[ 注:后缀expression式和参数expression式的求值都是相互不相关的。 参数expression式评估的所有副作用在input函数之前都被sorting(见1.9)。 – 结束注意 ]

(C ++ 11,§5.2.2/ 8)