I am trying to figure out how RVO and NRVO work along with the new C++11 move operators. I have drafted a dummy class with a few examples.
EDIT: Only most important part of the code is shown.
Full source code is available here.
I have two functions that get the class as reference and return either a value or a reference:
VOpt& fChangeClassRetRef(VOpt &m) {
m.setX(21);
return m;
}
VOpt fChangeClassRetValue(VOpt &m) {
m.setX(21);
return m;
}
When I call these functions I have as output the following:
VOpt &m14 = fChangeClassRetRef(m13);
m14 = fChangeClassRetRef(m11);
-> Copy Assignment Operator
m14 = fChangeClassRetValue(m11);
-> Copy Constructor
-> C++11 Move Operator
When an lvalue reference is used no copy constructors are invoked. Otherwise, those functions (that receive a reference as parameter) still call copy constructors.
Is this feature compiler dependent? Am I doing something wrong?
You have:
which was used this way:
Let's analyse:
#1
returns the name of an argument (not a local variable), so neither RVO nor NRVO applies here. NowfChangeClassRetRef
returns a reference to whereverm
is bound to, which, in #2 ism11
. Therefore, we're initializingm12
with an lvalue reference tom11
. In this case he compiler can't call the move constructor because it takes an rvalue and, as we have just seen, you are providing an lvalue. The copy constructor gets called.The other case is similar. You have
which is called this way:
As above, there's no RVO neither NRVO here because you're returning the name of an argument.
The function returns by value and you're returning an lvalue. (In some circunstances compilers are allowed to treat the returning lvalue as if it was an rvalue but not in this case.) Hence the move constructor cannot be called and the copy constructor is invoked.