7

Consider this function:

std::string 
myClass::myFunction2() {
  std::string result = myClass::myFunction1();
  return result;
}

I'm hoping that the compile performs return value optimization. How can I make sure this actually happens, and the code will not copy the result redundantly?

Ari
  • 7,251
  • 11
  • 40
  • 70
  • 2
    `g++ -S` is your friend: https://stackoverflow.com/questions/137038/how-do-you-get-assembler-output-from-c-c-source-in-gcc – NPE Aug 18 '17 at 21:26
  • 5
    Your first problem is your sample code isn't legal C++; I can fill in blanks (make up code to fix your build errors), but different blanks lead to different conclusions, so I refuse to. Post real code not pseudocode. Your second problem is that compilers, lacking being explicitly told not to, will elide if they can, and the rules for when they can are simple. Your third problem is caring, because even if not elided the cost of a string move is small and bounded. Barring profiling that is; and if you profile and examine assembly at hot spots you'll know. (The above won't be a hot spot) – Yakk - Adam Nevraumont Aug 18 '17 at 21:36
  • Use C++11 and later, and return types that have a valid move constructor. In C++11, thanks to move semantics, the standard is able to enforce elision of temporaries - including RVO - in some cases. As long as you stick within the cases that are specified in the standard, you'll be okay. Before C++11, it was not possible to force a compiler to do RVO in any way - support or otherwise by a compiler was a "quality of implementation concern", since the standard permitted but did not require RVO, so compilers did not have to do it. – Peter Aug 18 '17 at 22:17

1 Answers1

4

RVO is always applied, if possible. For your case, assuming myFunction1() does not return different named objects depending on the path of execution, the compiler should perform RVO. If it returns different named objects with different execution path, then the compiler is not able to perform optimization.

I recommend to do your own experiments:

To disable optimization everywhere, use pragmas:

#pragma GCC push_options
#pragma GCC optimize (ARG)

//your code

#pragma GCC pop_options

To disable optimization for a specific function, use __attribute__(()):

void __attribute__((optimize(ARG))) foo(unsigned char data) {
    // your code
}

ARG can either be numbers (i.e. an optimization level) or strings starting with 0 (i.e. an optimization option) and etc. For what you need, you can substitute ARG with "O0" Then run the both versions of your code using gcc -S to see the difference. I recommend you to read gcc 4.4 or newer doc.

Ali Abbasinasab
  • 382
  • 3
  • 13