1

Is -fno-elide-constructors contained in -O0 or any other -O[other level]?

In my view, -fno-elide-constructors is an optimization flag, and the -O is the optimization level. Hence, some -O level may include the flag -fno-elide-constructors. Am I right?

In other words, is there any relationship between -fno-elide-constructors and -O..?

pulsejet
  • 1,101
  • 13
  • 27
jiafu
  • 6,338
  • 12
  • 49
  • 73

1 Answers1

2

In other words, is there relationships between -fno-elide-constructors and -O..?

Yes there is a relationship, although a quite simple one: gcc will most likely elide constructors already at the -O0 level unless you explicitly disable it. See the example code at the bottom for proof.

It is tricky though, the compiler can do really nasty things, see RVO force compilation error on failure. The bottom line is: You always need to check the generated assembly to see what is really happening under the hood.

Please keep in mind (from Working Draft, Standard for Programming Language C++, N3797 which is the closest approximation of C++14 that I could find):

12.8/31 When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the constructor selected for the copy/move operation and/or the destructor for the object have side effects. [...]


The code substantiating my statement:

#include <cstdio>
constexpr int size = 1024;

struct A { int array[size] = { 0 }; };

int main() {
  A a = A();
  std::printf("%d\n", a.array[size-1]);
}

With g++ -std=c++11 -Wall -O0 -S elide.cpp, in the generated assembly code there is only a single

    call    A::A()

However, with g++ -std=c++11 -Wall -O0 -fno-elide-constructors -S elide.cpp I get:

    call    A::A()
    [...]
    call    A::A(A&&)

Even if you disable optimizations with -O0, you still have to disable elision additionally if you need it to be disabled for some reason.

Community
  • 1
  • 1
Ali
  • 56,466
  • 29
  • 168
  • 265
  • About the: `Because some compilers do not perform copy elision in every situation where it is allowed, programs that rely on the side-effects of copy/move constructors and destructors are not portable.` This is not exact. That behavior is specifically described in the standard (C++14 12.8/31 and /32, or even C++98 12.8/15), so it is "portable". It's just that some compilers will do more copies than others. A bit like "long" can be 32-bit in some platforms, and 64-bit in others. My guess is that if you need to disable RVO to make sure you'll have some behavior, you are doing something fishy.. – paercebal May 19 '15 at 15:25
  • @paercebal Thanks, fixed! I guess whoever wrote "portable" meant that if you switch to another compiler then strange things can happen... :( Yes, I totally agree, it is fishy if someone depends on this behavior. Anyway, updated my answer, thanks! – Ali May 19 '15 at 20:33