从已捕获的lambda中反复移动变量

时间:2018-04-16 01:50:32

标签: c++ c++11 lambda c++14 move-semantics

我有以下测试代码:

#include <iostream>
#include <string>

void printValue(std::string&& val)
{
    std::cout << "Got value: " << val << "\n";
}

int main() {

    std::string testValue = "Test Value";

    auto lambda = [testValue = std::move(testValue)]() mutable
    {
        printValue(std::move(testValue));
    };

    lambda();
    lambda();
    lambda();
}

我得到了结果:

Got value: Test Value
Got value: Test Value
Got value: Test Value

一个有效的假设是,从已被移动捕获的lambda中移动一个对象将始终具有它被移动到lambda中的初始状态,或者这只是一个对象的工件在&#34;有效但未指明的状态&#34;?

1 个答案:

答案 0 :(得分:21)

std::move不执行移动操作;它只是将参数转换为右值。对于您的代码,printValue通过rvalue-reference获取参数,因此参数testValue将通过引用传递。但是移动操作没有在它上面执行,然后testValue不会被改变。

如果您将val更改为按值传递,则参数testValue将移至val,或者您可以明确添加移动操作,如

void printValue(std::string&& val)
{
    std::cout << "Got value: " << val << "\n";
    std::string x = std::move(val);            // perform move operation on val
}

两者都会导致移动操作执行3次,然后你会得到不同的结果,例如与clang

Got value: Test Value
Got value: 
Got value: 

PS:正如你所说,在从对象移动构造后,将保持有效但未指定的状态。标准不保证上述行为,尽管大多数实现都这样做。