Search code examples
c++c++11move-constructorrvo

Why is the move constructor being called?


Given my understanding of return value optimization, I am a confused as to why the move constructor is being called in the sample code below:

#include <vector>
#include <iostream>

class MyCustomType
{
public:
  MyCustomType()
  {
    std::cout << "Constructor called" << std::endl;
  }

  MyCustomType(const MyCustomType & inOther) : // copy constructor
    mData(inOther.mData)
  {
    std::cout << "Copy constructor called" << std::endl;
  }

  MyCustomType(MyCustomType && inOther) : // move constructor
    mData(std::move(inOther.mData))
  {
    std::cout << "Move constructor called" << std::endl;
  }

private:
  std::vector<int> mData;
};

MyCustomType getCustomType()
{
  MyCustomType _customType;
  return _customType;
}

int main()
{
  MyCustomType _t = getCustomType();
}

Output:

Constructor called
Move constructor called

I assumed that there would only be a single instance of MyCustomType constructed and assigned directly to _t.

For info, I am using the VC14 compiler.


Solution

  • In your example you assume that NRVO will be applied. But NRVO is just an optimization, which is not guaranteed to be used by the compiler ^.

    I have tested your example with http://webcompiler.cloudapp.net/.

    The default set of compiler options there is:

    /EHsc /nologo /W4
    

    In such case the output is similar with yours:

    Constructor called
    
    Move constructor called
    

    But if appropriate optimization is enabled with, say, /O2 flag:

    /O2 /EHsc /nologo /W4
    

    Then the output is:

    Constructor called
    

    ^ As @einpoklum has mentioned in the comments, rules have changed since C++17.