事先道歉,我知道评估顺序的一般主题已经有很多SO问题。但是,在研究了它们之后,我想澄清一些具体的观点,我认为这些观点并不构成任何重复。假设我有以下代码:
#include <iostream>
auto myLambda(int& n)
{
++n;
return [](int param) { std::cout << "param: " << param << std::endl; };
}
int main()
{
int n{0};
myLambda(n)(n);
return 0;
}
上面的程序在编译时输出“n:0”。在这里,我们有未指定的顺序在起作用:如果执行了不同的评估顺序,它可能很容易输出“n:1”。
我的问题是:
myLambda(0)
,其参数n
和后续函数调用本身之间的顺序关系到底是什么? [](int param) { std::cout << "hello" << std::endl }
(即使结果独立于其参数,从而使任何评估顺序决定,从而确定行为),上述2)的答案是否仍将相同? 编辑:我已将lambda参数名称从'n'更改为'param',因为这似乎引起了困惑。
最佳答案
具有讽刺意味的是(由于该示例使用了C++ 11功能,并且使其他答案分散了注意力),使该示例具有未指定行为的逻辑可以追溯到C++ 98,第5节,第4段
本质上,所有C++标准中都存在相同的子句,尽管正如Marc van Leeuwen的评论所指出的那样,最近的C++标准不再使用序列点的概念。最终结果是相同的:在一条语句中,运算符的操作数的顺序或求值以及单个表达式的子表达式仍未指定。
发生未指定的行为是因为表达式n
在语句中被评估了两次
myLambda(n)(n);
表达式
n
的一个评估(以获得引用)与第一(n)
相关联,表达式n
的另一评估(获取值)与第二(n)
相关联。未指定这两个表达式的评估顺序(即使从表面上看,它们都是n
)。所有C++标准中都存在类似的子句,并且结果相同-不管
myLambda(n)(n)
如何实现,语句myLambda()
的未指定行为例如,可以在C++ 98(以及所有更高版本的C++标准,包括C++ 11和更高版本)中实现
myLambda()
。 class functor
{
functor() {};
int operator()(int n) { std::cout << "n: " << n << std::endl; };
};
functor myLambda(int &n)
{
++n;
return functor();
}
int main()
{
int n = 0;
myLambda(n)(n);
return 0;
}
因为问题中的代码只是一种(C++ 11)技术(或简称),用于实现与此相同的效果。
上面的答案回答了OP的问题1.和2.。未指定的行为发生在
main()
中,与myLambda()
本身的实现方式无关。为了回答OP的第三个问题,如果lambda(或本例中的仿函数的
operator()
)被修改为不访问其参数的值,则该行为仍未指定。唯一的区别是该程序作为一个整体不会产生可见的输出,而这些输出在编译器之间可能会有所不同。关于c++ - C++后缀表达式未定义与未指定行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37344370/