#include <string>
struct X
{
char y;
std::string z;
X & operator()(std::string && s)
{
z = std::move(s);
return *this;
}
X & operator()(char c)
{
y = c;
return *this;
}
};
int main()
{
X x;
std::string y("abc");
x(y[0])(std::move(y));
}
是main
的最后一行未定义的行为?我猜是的,因为它会扩展为以下内容,但只想确保对调用运算符或成员函数的调用没有更严格的保证X::operator()(&X::operator()(&x, y[0]), std::move(z))
请添加标准或cppref中的引用
最佳答案
在c++ 17之前,像您的示例一样,修改相同l值的链接函数调用确实是未定义的行为,因为这些表达式的求值顺序未指定。
但是,已修复了proposal并已合并到c++ 17中。
这是相关的rule(重点是我的),其中还包含提案中的示例,展示了其工作原理:
The postfix-expression is sequenced before each expression in the expression-list and any default argument. The initialization of a parameter, including every associated value computation and side effect, is indeterminately sequenced with respect to that of any other parameter. [Note: All side effects of argument evaluations are sequenced before the function is entered (see [intro.execution]). — end note] [Example:
void f() { std::string s = "but I have heard it works even if you don't believe in it"; s.replace(0, 4, "").replace(s.find("even"), 4, "only").replace(s.find(" don't"), 6, ""); assert(s == "I have heard it works only if you believe in it"); // OK }
— end example]
尽管上述规则仅严格引用内置的
operator()
,并且您具有用户定义的运算符,但由于存在rule,因此适用于评估顺序的相同规则:If either operand has a type that is a class or an enumeration, a user-defined operator function might be declared that implements this operator or a user-defined conversion can be necessary to convert the operand to a type that is appropriate for a built-in operator. ... However, the operands are sequenced in the order prescribed for the built-in operator.
关于c++ - 调用运算符参数评估顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63829690/