Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can the compiler implicitly std::move arguments when referenced just once?

Let's say I have a simple class with a setter:

class MyClass
{
public:
    void setName(std::string name)
    {
        _name = std::move(name);
    }

private:
    std::string _name;
};

I'm using std::move here, but if I were to omit this and just write _name = name, could the compiler implicitly move the name argument since it isn't used anywhere else in the setter? It can almost be treated as an rvalue in the assignment expression because it isn't being referenced by name anywhere else.

Can compilers do this? Do existing compilers do this?

like image 645
Mike Weller Avatar asked Dec 06 '13 09:12

Mike Weller


2 Answers

Adding on top of what Nawaz has said. Under the as-if rule, if the compiler can prove that the different behavior between move and copy is not observable, then it's allowed to make the move. (I believe this can be really hard for the compiler except for trivial types for which the gain of moving over coping doesn't exist anyway.)

I don't know if there's any compiler doing this. (I guess not!)

AFAIK, the only situations where an lvalue is treated as an rvalue, for overload resolution purposes, are in a return statement, throw expression and exception-declaration (i.e. the declaration of object in catch (type object)). In addition, some conditions (basically the same as copy elision) have to be met for this to happen:

When the criteria for elision of a copy operation are met or would be met save for the fact that the source object is a function parameter, and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue. [...]

Finally, notice that the situations mentioned above involve construction. They don't cover assignment as in the OP's question.

like image 85
Cassio Neri Avatar answered Sep 28 '22 04:09

Cassio Neri


It might do that if the compiler can prove it is safe to do that — it would be an optimization. But that is not required by the language. So to ensure the argument is moved, you've to do that explicitly as you've done — your setName() cannot be improved in this regard.

like image 22
Nawaz Avatar answered Sep 28 '22 04:09

Nawaz