0

Here is Example..!! Can you explain how it works? why Destruct just one time?

#include <iostream>
using namespace std;
class A {
public:
    A() {
        cout << "A's Construct" << endl;
    }
    ~A() {
        cout << "A's Destructr" << endl;
    }
    A(const A& obj) {
        cout << "A's Copy Constructor" << endl;
    }
};
A fun() {
    A obj;
    cout << "Fun" << endl;
    return obj;
}
int main() {
    A obj = fun();
    cout << "End" << endl;
    return 0;
}

and when I run above program output is:

A's Construct
Fun
End
A's Destructor

But When I remove Copy Constructor from the above code then Output is:

A's Construct
Fun
A's Destructor
End
A's Destructr

I'm expecting 2 Destructor for function's obj and main's obj and 1 time Copy Constructor for A obj=fun(); and one time Simple constructor for Function's object.

Expecting Output:

A's Construct
Fun
A's Destructor
A's Copy Constructor
End
A's Destructr

Can you explain the difference? I know there is Move semantics or RVO But I'm confused how they performing in this code?

Compiled in Visual Studio 2015.

  • 1
    I think you should also make some debugging output for the move constructor, then it will be more clear. – Chris Beck Sep 06 '15 at 18:21
  • @ChrisBeck how? I write the move constructor but not worked.. –  Sep 06 '15 at 18:22
  • 1
    I don't think there is any move happening here anywhere. – MikeMB Sep 06 '15 at 18:27
  • @MikeMB as I expecting. There should be one Copy Constructor for Main's object and 2 Destructor? then why it showing this output? –  Sep 06 '15 at 18:31
  • 1
    Can't reproduce with clang : [with copy constructor](http://coliru.stacked-crooked.com/a/82fe159e67a1887e) and [without](http://coliru.stacked-crooked.com/a/33ba46b680a75fb2) have the same output. – Pradhan Sep 06 '15 at 18:43
  • 2
    Nothing to do with move semantics, this is just [copy elision](https://en.wikipedia.org/wiki/Copy_elision) (and this is a duplicate of a thousand stackoverflow questions). – Jonathan Wakely Sep 06 '15 at 18:49
  • @JonathanWakely I tied about reading copy_elision but don't know exactly how it works. Can you explain my code please? –  Sep 06 '15 at 18:50
  • 1
    No, please just read about copy elision, e.g. the wikipedia article I linked to. It's been explained a thousand times already. Also read the [RVO](https://en.wikipedia.org/wiki/Return_value_optimization) page which has an example almost exactly like yours. – Jonathan Wakely Sep 06 '15 at 18:52
  • 1
    Also you "Expecting Output:" makes no sense, the copy constructor cannot copy an object that has already been destroyed. – Jonathan Wakely Sep 06 '15 at 18:54
  • This is just [RVO](https://en.wikipedia.org/wiki/Return_value_optimization) which has a Wikipedia page that explains it in detail. Basically, the compiler is allowed to construct the object where it needs to be after it's returned, so there's no need to make a copy because it's already where the copy would be. – David Schwartz Sep 06 '15 at 18:56
  • @JonathanWakely VS providing my expecting output in debug mood..!! Any how I need to again read copy elision deeply and moree deeply..!! –  Sep 06 '15 at 18:57
  • @JonathanWakely: What I don't quite understand, is,why the OP ends up with more objects, when the user defined copy constructor is removed.(A devault move constructor should not be generated in either case right?) – MikeMB Sep 08 '15 at 14:32
  • @MikeMB, right, there should be no generated move ctor because of the user-defined destructor, but I gave up reasoning about VC++'s approach to copy elision long ago :) – Jonathan Wakely Sep 08 '15 at 14:44

2 Answers2

1

...[a little time passes]...

As one can read in the answers of the duplicate question this result is due to compiler optimizations:

Copy elision is an optimization implemented by most compilers to prevent extra (potentially expensive) copies in certain situations. It makes returning by value or pass-by-value feasible in practice (restrictions apply).

by @Luchian Grigore

Community
  • 1
  • 1
Ziezi
  • 6,375
  • 3
  • 39
  • 49
  • 1
    why the destruct for just one time? Where Function's object destructor? –  Sep 06 '15 at 18:24
  • @simplics but I'm expecting 2 destructor and 1 copy constructor..!! Copy Constructor for main's function.. –  Sep 06 '15 at 18:30
  • I explicitly write Copy Const, then why not printing output? can you explain please? –  Sep 06 '15 at 18:35
  • can you explain the output please? I'm expecting `A's Construct Fun A's Destructor A's Copy Constructor End A's Destructr` with my copy constructor then why not this output? –  Sep 06 '15 at 18:40
  • I would appreciate some explanation for the negative vote. Thanks! – Ziezi Sep 06 '15 at 18:47
  • 1
    How is the term shallow copy relevant here? – MikeMB Sep 08 '15 at 13:47
  • @MikeMB when he deletes the explicitly defined `copy constructor` and asks: "Can you explain the difference?". One of the differences is that in the absence of copy constructor, the returning value is a shallow copy of the object inside the function (as it is not returned by reference) – Ziezi Sep 08 '15 at 14:03
  • 1
    HIs explicit copy constructor was a "shallow" copy too. More to the point: For a class without any datamembers, there is not difference between shallow and deep copy. – MikeMB Sep 08 '15 at 14:18
  • @MikeMB OK, now I got you point! I'm editing and removing the most of the speculations in my answer. Thanks! :) – Ziezi Sep 08 '15 at 14:20
  • @MikeMB now the answer is, at least contributing `0`, instead of wrong information `-1` :) – Ziezi Sep 08 '15 at 14:28
  • *"But on the other side you have only a default constructor, so every object instantiation is performed by it."* Doesn't make sense. There is still a (compiler generated) copy constructor and if there wasn't (e.g. when using `=delete`) The code would not compile in the first place. – MikeMB Sep 08 '15 at 15:08
  • @MikeMB I see, well, second edit done. – Ziezi Sep 08 '15 at 16:46
0

Case 1: with copy constructor, output is:

A's Construct
Fun
A's Copy Constructor  
//A will copy before destroying, unlike what you expecte that A should destroy before copying
A's Destructr
End
A's Destructr

I think is expected and self explanatory

Case 2: No copy constructor, output is,

A's Construct
Fun
//A has copied here by calling the default constructor provided by the compiler
A's Destructr
End
A's Destructr

VS2015

Acha Bill
  • 1,255
  • 1
  • 7
  • 20
  • but with copy constructor why output is different? as you write output is expected. but VS2015 not providing that. –  Sep 06 '15 at 18:48
  • my VS2015 provides that output for the 2 cases from your code. The first case is expected from you and that's what i have. So no issues with that. The second case is explained below. – Acha Bill Sep 06 '15 at 18:51
  • are you using release mode? –  Sep 06 '15 at 18:52
  • got the point Thanks. it's copy elision..!! –  Sep 06 '15 at 18:54
  • @LetDoit i edited the answer and i'm using VS2015 Enterprise. – Acha Bill Sep 06 '15 at 18:55