2

Consider this:

#include <iostream> struct A{ A(){ std::cout << "Create empty A" << std::endl; } A(const A& a){ // Why is this never called?? std::cout << "Never called" << std::endl; } }; A genA() { A a; return a; } int main(int argc, const char *argv[]) { A a(genA()); // Expected to call copy constructor return 0; } 

Why is the copy constructor not called?

What should I do if I want to ensure that "Never called" is printed on the screen every time I copy A.

3
  • don't forget to add a copy constructor to catch other cases of assigning copies. "A& operator(const A& a) {... return *this}" Commented Aug 24, 2011 at 10:19
  • 1
    In GCC you can say -fno-elide-constructors to disable the copy elision. Commented Aug 24, 2011 at 10:24
  • @Allan: "Never Called" will be printed every time there is a copy of 'A'. The problem here is that no copy is made because of NRVO. The question then becomes do you want to force it for some reason or are you just curious why your code was not acting as expected? Commented Aug 24, 2011 at 10:28

3 Answers 3

7

This is called as Return value optimization.
Compiler can optimize your code so that it bulds the object directly in the location where it would have been copied too. Thus there will be no reason to use the copy constructor.

Note: The standard explicitly allows it do so.

Sign up to request clarification or add additional context in comments.

1 Comment

NRVO (not RVO)... to be exactly.
2

One way you can force the compiler to avoid RVO is to not return by value - e.g.

#include <iostream> #include <memory> struct A{ A() { std::cout << "Create empty A" << std::endl; } A(const A& a) { // This will be called now std::cout << "Never called" << std::endl; } }; std::auto_ptr<A> genA() { return std::auto_ptr<A>(new A); } int main(int argc, const char *argv[]) { A a(*(genA().get())); // this will trigger the copy-ctor return 0; } 

Though this is a horrible hack. I would instead ask why you want to do this? and if you are hoping to put some side-effects into the constructor, urge you to think otherwise.

1 Comment

The only side effects in a copy constuctur that work are those related to object construction, counting the number of live objects for instance.
1

Copy constructor invocations can be elided (even if they contain side effects), the standard allows that ([12.2]).

EDIT:

I suggest that you do not try to fight it in real world code.

If you just want to see the copy ctor executed in some example/turorial code, then it usually helps not to compile with optimization. Some compilers even have switches that help to avoid that. For GCC it should be -fno-elide-constructors.

6 Comments

That's called Return Value Optimization - en.wikipedia.org/wiki/Return_value_optimization
@duedl0r: The reason is that it is a very easy optimization to write into the compiler. The one stubling block that by removing the copy construction you can change behavior of the code as the copy constructor can potentially have side affects. Thus the standard explicitly states that this optimization is allowed even if the copy constructor did have side affects. Note: It is bad practice for the constructor to have side affects.
@Martin, like I said, the OP wants to know how to avoid this, so I guess this is a partial answer at best?
@Nim: The way I read it, is that he wants it because he expects it to happen and does not understand why his code is not working as expected (so he wants to force it). The trouble is the code is already working (just not as expected). Thus the question may be phrased as how do I force this but all he really wants is the object to be correctly created outside the function.
@Martin: It is not possible to avoid it without employing something compiler specific.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.