Is std::move really needed on initialization list of constructor for heavy members passed by value?

My question: is this std::move really needed? My point is that
compiler sees that this p_name is not used in the body of constructor,
so, maybe, there is some rule to use move semantics for it by default?

In general, when you want to turn an lvalue to an rvalue, then yes, you need a std::move(). See also Do C++11 compilers turn local variables into rvalues when they can during code optimization?

void President::setDefaultName()
{
   std::string local = "SO";
   name = local; // std::move OR not std::move?
}

For me this local variable is expiring variable – so move semantics
could be applied… And this similar to arguments passed by value….

Here, I would want the optimizer to eliminate the superfluous local ALTOGETHER; unfortunately, it is not the case in practice. Compiler optimizations get tricky when heap memory comes in to play, see BoostCon 2013 Keynote: Chandler Carruth: Optimizing the Emergent Structures of C++. One of my takeaways from Chandler’s talk is that optimizers simply tend to give up when it comes to heap allocated memory.

See the code below for a disappointing example. I don’t use std::string in this example because that’s a heavily optimized class with inline assembly code, often yielding counterintuitive generated code. To add injury to insult, std::string is roughly speaking a reference counted shared pointer in gcc 4.7.2 at least (copy-on-write optimization, now forbidden by the 2011 standard for std::string). So the example code without std::string:

#include <algorithm>
#include <cstdio>

int main() {
   char literal[] = { "string literal" };
   int len = sizeof literal;
   char* buffer = new char[len];
   std::copy(literal, literal+len, buffer);
   std::printf("%s\n", buffer);
   delete[] buffer;
}

Clearly, according to the “as-if” rule, the generated code could be optimized to this:

int main() {
   std::printf("string literal\n");
}

I have tried it with GCC 4.9.0 and Clang 3.5 with link time optimizations enabled (LTO), and none of them could optimize the code to this level. I looked at the generated assembly code: They both allocated the memory on the heap and did the copy. Well, yeah, that’s disappointing.

Stack allocated memory is different though:

#include <algorithm>
#include <cstdio>

int main() {
   char literal[] = { "string literal" };
   const int len = sizeof literal;
   char buffer[len];
   std::copy(literal, literal+len, buffer);
   std::printf("%s\n", buffer);
}

I have checked the assembly code: Here, the compiler is able to reduce the code to basically just std::printf("string literal\n");.

So my expectations that the superfluous local in your example code could be eliminated is not completely unsupported: As my latter example with the stack allocated array shows, it can be done.

Imagine hundreds of KLOC project written in C++03 – shall we add everywhere this std::move?
[…]
But I am not sure: passing by value is rather not universal reference?

“Want speed? Measure.” (by Howard Hinnant)

You can easily find yourself in a situation that you do your optimizations just to find out that your optimizations made the code slower. 🙁 My advice is the same as Howard Hinnant’s: Measure.

std::string getName()
{
   std::string local = "Hello SO!";
   return local; // std::move(local) is not needed nor probably correct
}

Yes, but we have rules for this special case: It is called named return value optimization (NRVO).

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)