Search code examples
c++c++11compiler-optimizationmove-semanticscopy-elision

Will compilers apply move semantics automatically in a setter method?


I want to know if the compiler is allowed to automatically use the move constructor for wstring in the following setter method (without an explicit call to std::move):

void SetString(std::wstring str)
{
    m_str = str;  // Will str be moved into m_str automatically or is std::move(str) needed?
}

From what I've read it sounds as though the compiler is not allowed to make this decision since str is an lvalue, but it seems pretty obvious that using move here would not change program behavior.

Barring move, will some other sort of copy elision be applied?


Solution

  • [is] the compiler [...] allowed to automatically use the move constructor

    Yes, it would be nice. But this is not only an optimization, this has real impact on the language.

    Consider a move-only type like unique_ptr:

    std::unique_ptr<int> f()
    {
      std::unique_ptr<int> up;
      return up; // this is ok although unique_ptr is non-copyable.
    }
    

    Let's assume your rule would be included into the C++ standard, called the rule of "argument's last occurence".

    void SetString(std::unique_ptr<int> data)
    {
        m_data = data; // this must be ok because this is "argument's last occurence"
    }
    

    Checking if an identifier is used in a return is easy. Checking if it is "argument's last occurence" isn't.

    void SetString(std::unique_ptr<int> data)
    {
        if (condition) {
          m_data = data; // this is argument's last occurence
        } else {
          data.foo();
          m_data = data; // this is argument's last occurence too
        }
        // many lines of code without access to data
    }
    

    This is valid code too. So each compiler would be required to check for "argument's last occurence", wich isn't an easy thing. To do so, he would have to scan the whole function just to decide if the first line is valid. It is also difficult to reason about as a human if you have to scroll 2 pages down to check this.

    No, the compiler isn't allowed to in C++11. And he probably won't be allowed in future standards because this feature is very difficult to implement in compilers in general, and it is just a convenience for the user.