Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 通过移动捕获同一语句中使用的变量_C++_Gcc_Lambda_C++14_Move Semantics - Fatal编程技术网

C++ 通过移动捕获同一语句中使用的变量

C++ 通过移动捕获同一语句中使用的变量,c++,gcc,lambda,c++14,move-semantics,C++,Gcc,Lambda,C++14,Move Semantics,编辑:标记为重复(某种程度上,没有未定义的行为,只是未指定),我被移动捕获lambda的人为复杂性所愚弄,这与此无关 我和我的同事发现,当我们在同一语句中通过常量引用使用变量后,试图通过move捕获变量时,GCC 6、7和Clang之间存在一个奇怪的差异。 一个简单的例子: #include <iostream> #include <string> struct A { template <class F> void call (F f) {

编辑:标记为重复(某种程度上,没有未定义的行为,只是未指定),我被移动捕获lambda的人为复杂性所愚弄,这与此无关

我和我的同事发现,当我们在同一语句中通过常量引用使用变量后,试图通过move捕获变量时,GCC 6、7和Clang之间存在一个奇怪的差异。 一个简单的例子:

#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: hello
in lambda: hello
注意,使用两个语句,即
autot=test;t、 调用(…)给出了与GCC 6.3相同的(第二)结果。我们天真地期望第二个输出无处不在:它是GCC6错误、未定义的行为还是标准更改


对于信息,我们的“实际”案例是异步调用:
test
是调用,
struct A
是预期回调的结果。

在C++14中,未指定是先计算
test
还是先计算lambda表达式。但是,没有未定义的行为(假设
test
不会使用从
移动的字符串触发UB)


在C++17中,
test(s)
总是在lambda之前进行评估。

您的问题可以简化为类似于
foo(i).call(i++)。即未指明的结果。我认为这不是一个真正合适的重复;结果不是一个未定义的行为,但我假设了一个未指定的行为。事实上,它只是与序列点有关。然而,在玩Wandbox时,它似乎与标准版本无关,而是与GCC版本相关:GCC 6.3,使用--std=c++14或c++17:move是首先完成的,而GCC 7.1,使用这两种标准,move是在之后完成的。编辑:@FrédéricSamier看起来C++17的大部分新东西只在7中出现,这并不奇怪。
in method: hello
in lambda: hello