Search code examples
c++rvalue-reference

std::move in function parameter will not use again?


I know if you use std::move(s), then the s can not use again, But I have some questions.

If I don't do move constructor/assignment operator, Does the variable still exist?

// 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;
}

Above test seems it exist, So is this the best practice to use std::move in a while loop below.

// 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;
        }
    }
}

seems if you don't do move assignment operator the s is still exist next loop, when it success then it do move assignment operator and break the loop, There seems to be no logical error, but I want to know if this is the best practice ? Because you need to handle data carefully.


Solution

  • I know if you use std::move(s), then the s can not use again

    That's not really true.

    After an object of a standard library type has been moved-from, unless otherwise stated its state is "valid but unspecified", so indeed it's best not to use it again unless you know you've put it back into a useful state (e.g. .clear() on a vector). (If the object is of one of your own types, you define those rules.)

    But std::move doesn't move anything. It only prepares your expression for triggering a move. If that didn't occur, then literally nothing happened, and you can keep using s without fear.

    However, you will confuse readers of your code. If you're not passing the result of std::move(s) to a move constructor or move assignment operator, best not write it at all.

    seems if you don't do move assignment operator the s is still exist next loop, when it success then it do move assignment operator and break the loop, There seems to be no logical error, but I want to know if this is the best practice ?

    It's correct, but it's kind of hard to read and follow, so it might be best to find some clearer way to structure it.

    Because you need to handle data carefully.

    Indeed.


    Ideally, both test1 and test2 would take const std::string& (since neither of them take ownership of the string), and then it will also be clear to the author of main that they needn't/shouldn't write std::move there: it would be harmless, but pointless.