编辑:标记为重复(有点,没有未定义的行为,只是未指定),我被移动的lambda捕获的人为复杂性所欺骗,这是无关紧要的。
我的同事和我发现GCC 6,7和Clang之间存在奇怪的差异,当我们尝试通过在之后移动来获取变量时,在同一语句中使用const引用。 一个最小的例子:
LoggingAdapter.process()
Wandbox链接:https://wandbox.org/permlink/TMoB6EQ7RxTJrxjm
GCC 6.3中的输出:
#include <iostream>
#include <string>
struct A
{
template <class F> void call (F f)
{
f();
}
};
A test(const std::string& s)
{
std::cout << "in method: " << s << std::endl;
return {};
}
int main()
{
std::string s = "hello";
test(s).call([s = std::move(s)] { std::cout << "in lambda: " << s << std::endl;});
return 0;
}
GCC 7.2和Clang中的输出:
in method:
in lambda: hello
请注意,使用两个语句,即in method: hello
in lambda: hello
,可以得到与GCC 6.3相同的(第二个)结果。我们天真地期待到处都是第二个输出:它是GCC 6错误,未定义的行为还是标准的变化?
有关信息,我们的“真实”情况是异步调用:auto t = test(s); t.call(...);
是调用,test
是期望回调的结果。
答案 0 :(得分:3)
在C ++ 14中,未指定是先评估test(s)
还是先评估lambda表达式。但是,没有未定义的行为(假设test
没有触发UB与移动的string
)。
在C ++ 17中,test(s)
始终在lambda之前进行评估。