10

Why is nothing being printed in this example? I'm compiling in Clang on Coliru.

#include <iostream>

struct S
{
    S()    noexcept = default;
    S(S&&) noexcept { std::cout << "move-ctor"; }
};

void f(S) {}

int main()
{
    f(S{});
}
user2030677
  • 3,448
  • 4
  • 23
  • 36
  • possible duplicate of [C++11 move constructor not called, default constructor preferred](http://stackoverflow.com/questions/13099603/c11-move-constructor-not-called-default-constructor-preferred) – jogojapan Jun 01 '13 at 12:41
  • Possible duplicate of [What are copy elision and return value optimization?](https://stackoverflow.com/questions/12953127/what-are-copy-elision-and-return-value-optimization) – underscore_d Apr 17 '18 at 10:26

1 Answers1

11

The compiler is performing copy elision, which is allowed per paragraph 12.8/31 of the C++11 Standard even if your move constructor, copy constructor, or destructor have side effects:

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 term copy elision is used even when a move is being elided:

This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):

[...]

— when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move

[...]

With GCC, you can use the -fno-elide-constructors to inhibit copy elision. In this case, you would see that the move constructor gets invoked, as in this live example.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • Why is it called copy elision if I am moving? – user2030677 Jun 01 '13 at 12:38
  • 1
    @user2030677: That's Standardese terminology. Mostly for historical reasons (in C++03 only copies could be elided, since move semantics did not exist) – Andy Prowl Jun 01 '13 at 12:39
  • @user2030677 you are eliding a *copy*, which could have been performed with the copy constructor, or the copy move constructor. – juanchopanza Jun 01 '13 at 12:40
  • Another question: How do I stop RVO/NRVO from happening? Is there a linker option for that? – user2030677 Jun 01 '13 at 13:13
  • @user2030677: RVO/NRVO is actually copy elision, so on GCC that's the flag I wrote about at the end of my answer (btw, copy elision is a compiler's job, not a linker's job). On Clang, the flag is the same, but that option has a bug in Clang, so I'd suggest not to use it. On MSVC I am not sure (perhaps try disabling all optimizations in Debug build) – Andy Prowl Jun 01 '13 at 13:15
  • But I did include that flag and its not working -- http://coliru.stacked-crooked.com/view?id=e86f35489281a37bf1e0557bf350db42-41475e255c735859f2b181fd0d057a6f – user2030677 Jun 01 '13 at 13:17
  • @user2030677: Sorry, I forgot an `s` (edited the answer): it is `-fno-elide-constructors`. But again, Clang has a bug with that, so I suggest using GCC for testing it – Andy Prowl Jun 01 '13 at 13:19
  • Where can I find a GCC compiler to do that? Liveworkspace is down and (AFAIK) ideone doesn't allow me to use the command line. – user2030677 Jun 01 '13 at 13:21
  • @user2030677: Coliru does (see the live example I linked in my question). Just use `g++-4.8` instead of `clang++` – Andy Prowl Jun 01 '13 at 13:22
  • I didn't know I could do that. Thanks. Where can I find info on more stuff like that? – user2030677 Jun 01 '13 at 13:25
  • @user2030677: What do you mean by "stuff like that"? :D Coliru? I don't know, I've just seen people used it this way and did the same – Andy Prowl Jun 01 '13 at 13:25
  • I meant like a list of compiler options like the one you showed me. – user2030677 Jun 01 '13 at 13:27
  • @user2030677: That depends on the compiler. You should check the compiler's documentation – Andy Prowl Jun 01 '13 at 13:34