0

I got this code:

Edit: The full code:

#include <iostream>
using namespace std;

class A {
    public:
    A() {}
    A(const A& a) {
         cout << "A copy ctor" << endl;
    }
    virtual ~A() {
         cout << "A dtor" << endl; 

    }
    virtual void type() const { 
        cout << "This is A" << endl; 

    }
};

class B: public A {
    public:
    B(){}
    virtual ~B() {
         cout << "B dtor" << endl; 
    }
    void type() const override {
         cout << "This is B" << endl; 
    }
};

A f(A a) {
    a.type();
    return a;
}

const A& g(const A& a) {
    a.type();
    return a;
}

int main() {
    A* pa = new B();
    cout << "applying function f:" << endl;
    f(*pa).type();
    cout << "applying function g:" << endl;
    g(*pa).type();
    delete pa;
    return 0;
}

I noticed when debugging the code that after making and passing a copy of *pa to f and ending the function the destructor of the copy (*pa) that was passed to f is not called. Only when type() ended (the same line) both the copies (I assume) were erased by the destructors

I was sure that when ending the function a destructor will be called and erase the current copy which did not happened in this case. I would like to get an explanation to the order in which the constructors and desturctors are being called in the code (I am not very knowledgeable about the order when methods are involved and I could not find much about it online).

thank you.

  • Does this answer your question? [When to use virtual destructors?](https://stackoverflow.com/questions/461203/when-to-use-virtual-destructors) – kesarling He-Him Jun 29 '20 at 18:20
  • 6
    Also note that the call `f(*pa)` will [*slice*](https://stackoverflow.com/questions/274626/what-is-object-slicing) the object pointed to by `pa`. – Some programmer dude Jun 29 '20 at 18:22
  • 1
    @Someprogrammerdude I am aware about the slicing, the code was given to me so I cant edit it. – Idan Musayev Jun 29 '20 at 18:24
  • @d4rk4ng31 My question is why both copies are erased at the end of line 2 and why the copy that was passed to f was not erased at the end of the function. – Idan Musayev Jun 29 '20 at 18:26
  • @NicolBolas I have writen in the question that i found it while debugging the code. – Idan Musayev Jun 29 '20 at 18:31
  • 2
    @IdanMusayev `*pa` creates a temporary `A` on line 2, so it's destructed as the last step of line 2's execution. (Temporaries are destroyed only after the full-expression they appear in is completely evaluated -- unless they are bound to a reference, that is.) There's no call to `B`'s destructor since no `B` was created on that line. – cdhowie Jun 29 '20 at 18:35
  • @d4rk4ng31 I edited the code and replaced it with the entire code – Idan Musayev Jun 29 '20 at 18:37

1 Answers1

2

When you do f(*pa).type();, the Copy Constructor of A is called with an A object, so it will create an A to pass into your f function. When f returns, it is a different A being returned, since it's not by ref, however, it is NOT immediately destroyed, and instead uses copy-elision to stick around until after the .type() is called.

After that point, the destructor of both the temporary object passed into f, and the temporary object return by f are destroyed, so ~A() gets called twice.

ChrisMM
  • 8,448
  • 13
  • 29
  • 48
  • I did not ear about the copy-elision term before (at least by name) so I will dig up on it online. Can you elaborate on the order in which the objects are destroyed? thank you. – Idan Musayev Jun 29 '20 at 18:52
  • 1
    @IdanMusayev In this case, I'm not sure if the order is guaranteed between which object gets destroyed first, since they both go out of scope at the same time. Someone else might be able to answer that. – ChrisMM Jun 30 '20 at 00:42