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.
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.