提问者:小点点

std::move in函数参数不会再次使用?


我知道如果您使用std::move(s),那么s就不能再使用了,但是我有一些问题。

如果我不执行移动构造函数/赋值运算符,变量是否仍然存在?

// not do assignment
void test2(string &&t) {
    return;
}

void test1(string &&s) {
    test2(std::move(s));
}

int main()
{
    string s("123");
    
    test1(std::move(s));
    cout << "s: " << s << endl;
}

上面的测试似乎存在,所以这是在下面的while循环中使用std::move的最佳实践。

// do assignment
bool test4(string &&t) {
    if (condition) {
        return false;
    }
    
    string m = std::move(t);
    
    return true;
}

void test3(string &&s) {
    while(true) {
        if( test4(std::move(s)) ) {
            break;
        }
    }
}

似乎如果你不做移动赋值运算符,s仍然存在下一个循环,当它成功时,它做移动赋值运算符并打破循环,似乎没有逻辑错误,但我想知道这是否是最佳实践?因为您需要小心地处理数据。


共1个答案

匿名用户

我知道如果你使用std::move(s),那么s就不能再使用了

那不是真的。

在标准库类型的对象被移出之后,除非另有说明,否则它的状态是“有效但未指定的”,因此实际上最好不要再次使用它,除非您知道您已经将它放回了有用的状态(例如,向量上的.clear())。(如果对象是您自己的类型之一,则定义这些规则。)

但是std::move不会移动任何东西。它只是为触发移动而准备你的表情。如果没有发生这种情况,那么实际上什么也没有发生,您可以继续使用s而不必担心。

但是,您会使代码的读者感到困惑。如果您没有将std::move(s)的结果传递给移动构造函数或移动赋值运算符,最好不要编写它。

似乎如果你不做移动赋值运算符s仍然存在下一个循环,当它成功时它做移动赋值运算符并打破循环,似乎没有逻辑错误,但我想知道这是不是最好的做法?

它是正确的,但是它很难读懂和理解,所以最好找到一些更清晰的方法来构造它。

因为您需要小心地处理数据。

的确如此。

理想情况下,test1test2都将接受const std::string&;(因为它们都不接受字符串的所有权),然后,main的作者也会清楚,他们不需要/不应该在那里编写std::move:这将是无害的,但毫无意义的。