Hello, I have been revisiting the so-called return value optimizations, and I found some things which I cannot fully grasp. Basically, the issue is about the difference between return value optimization and constructor elison; and how they are controlled within GCC. ----------------------------- ---- Test program ---- ----------------------------- Take main.cc as //// #include <iostream> class A { public: A(const A&) { std::cout << "-\n"; } A() { std::cout << "*\n"; } A& operator=(const A&) { std::cout << "=\n"; return *this; } }; A f() { A a; return a; } int main() { A a = f(); } //// ------------------------------ ---- GCC's version ---- ------------------------------ r$ g++ --version g++ (Ubuntu 4.3.3-5ubuntu4) 4.3.3 Copyright (C) 2008 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ---------------------- ---- CASES ---- ---------------------- In order to see what's happening I ran 1) r$ g++ main.cc r$ ./a.out * 2) r$ g++ -fno-elide-constructors main.cc r$ ./a.out * - - 3) r$ g++ -fdump-tree-nrv main.cc r$ ls a.out main.cc r$ ./a.out * 4) r$ g++ -O1 -fdump-tree-nrv main.cc r$ ls a.out main.cc main.cc.127t.nrv r$ ./a.out * 5) r$ g++ -O1 -fdump-tree-nrv -fno-elide-constructors main.cc r$ ls a.out main.cc main.cc.127t.nrv r$ ./a.out * - - r$ mv main.cc.127t.nrv main.cc.127t.nrv.no-elide r$ g++ -O1 -fdump-tree-nrv main.cc r$ ./a.out * r$ ls a.out main.cc main.cc.127t.nrv main.cc.127t.nrv.no-elide r$ diff main.cc.127t.nrv main.cc.127t.nrv.no-elide 20a21 > __ostream_insert (&cout, &"-\n"[0], 2); 32a34 > __ostream_insert (&cout, &"-\n"[0], 2); 6) r$ g++ -Q --help=c++ | grep elide -felide-constructors r$ g++ --help=c++ | grep elide -felide-constructors This switch lacks documentation 7) man g++ ... -fno-elide-constructors The C++ standard allows an implementation to omit creating a temporary which is only used to initialize another object of the same type. Specifying this option disables that optimization, and forces G++ to call the copy constructor in all cases. ... Not all optimizations are controlled directly by a flag. Only optimizations that have a flag are listed. 8) r$ g++ -fdump-tree-optimized -fdump-tree-original -fno-elide-constructors main.cc r$ ls a.out main.cc main.cc.003t.original 9) r$ g++ -fdump-tree-original -fno-elide-constructors main.cc r$ mv main.cc.003t.original main.cc.003t.original.no-elide r$ g++ -fdump-tree-original main.cc r$ gvimdiff main.cc.003t.original main.cc.003t.original.no-elide 2 files to edit (omit the contents for brevity) ------------------------------------ ---- OBSERVATIONS ---- ------------------------------------ - Given 3 & 4: NRV is not enabled with -O0 (the default optimization level) but it's with -O1. There's no individual flag for NRV (as the man allows in the 2nd paragraph in 7). - Given 1: Construction elison is taking place even at -O0; but the first command of 6 doesn't show an [enabled] tag for it. - Given 5: The constructors are being inlined in the no-elided version, so more than the call (as the man says in 7) when "no-elide-constructors" you force the execution of the body (of course, if no call, no execution). - Given 8: Constructor elison is not a tree based optimization. - Given 9: Constructor elison is performed before tree based optimization. - In the file generated by 4 called "main.cc.127t.nrv" I see a "return slot optimization" label. ----------------------------- So, we have: - Named return value optimization. - Return slot optimization. - Construction elison optimization. What's the relation between them? Which are the differences and similarities? On one hand, construction elison seems to be a more general thing than nrv (from previous knowledge I understand nrv to be an optimization avoiding calls to constructors in return statements). But we saw that elison is applied without nrv taking place, but that may be an artifact of how certain cases are handled in GCC (tree based optimization or another technique). Cheers, thanks a lot, and have a happy new year. -- Rodolfo Federico Gamarra