通过移动同一语句中使用的变量进行捕获
Capture by move of variable used in the same statement
编辑:标记为重复(有点,没有未定义的行为,只有未指定),我被移动捕获 lambda 的人为复杂性所愚弄,这无关紧要。
我的同事和我发现 GCC 6、7 和 Clang 之间存在奇怪的差异,当我们尝试通过移动 after 在同一语句中通过 const 引用使用它来捕获变量时.
一个最小的例子:
#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;
}
魔杖盒link:https://wandbox.org/permlink/TMoB6EQ7RxTJrxjm
GCC 6.3 中的输出:
in method:
in lambda: hello
GCC 7.2 和 Clang 中的输出:
in method: hello
in lambda: hello
请注意,使用两个语句,即 auto t = test(s); t.call(...);
给出与 GCC 6.3 相同的(第二个)结果。我们天真地期待到处都是第二个输出:它是 GCC 6 错误、未定义的行为还是标准更改?
请注意,我们的 "real-life" 案例是异步调用:test
是调用,struct A
是需要回调的结果。
在 C++14 中,未指定是先计算 test(s)
还是先计算 lambda 表达式。但是,没有未定义的行为(假设 test
不会触发 UB 并从 string
移出)。
在 C++17 中,test(s)
总是在 lambda 之前求值。
编辑:标记为重复(有点,没有未定义的行为,只有未指定),我被移动捕获 lambda 的人为复杂性所愚弄,这无关紧要。
我的同事和我发现 GCC 6、7 和 Clang 之间存在奇怪的差异,当我们尝试通过移动 after 在同一语句中通过 const 引用使用它来捕获变量时. 一个最小的例子:
#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;
}
魔杖盒link:https://wandbox.org/permlink/TMoB6EQ7RxTJrxjm
GCC 6.3 中的输出:
in method:
in lambda: hello
GCC 7.2 和 Clang 中的输出:
in method: hello
in lambda: hello
请注意,使用两个语句,即 auto t = test(s); t.call(...);
给出与 GCC 6.3 相同的(第二个)结果。我们天真地期待到处都是第二个输出:它是 GCC 6 错误、未定义的行为还是标准更改?
请注意,我们的 "real-life" 案例是异步调用:test
是调用,struct A
是需要回调的结果。
在 C++14 中,未指定是先计算 test(s)
还是先计算 lambda 表达式。但是,没有未定义的行为(假设 test
不会触发 UB 并从 string
移出)。
在 C++17 中,test(s)
总是在 lambda 之前求值。