1

so I'm starting to learn c++ and got around pointers, constructors, destructors, allocation, heap/stack memory.

I have already figured out that local variables created inside functions are allocated on the stack and destructed (or deleted?) after the function return, unless we allocate it on the heap using new and thus being able to return a pointer to it.

My question is: why is Teest class desctructor not called on this code example after go() returns?

#include <iostream>

using namespace std;


class Teest {
public:
    Teest() {
        cout << "Constructed " << ++c << endl;
    }

    Teest(const Teest&) {
        cout << "copy constructor" << endl;
    };
    Teest& operator=(const Teest&) {
        cout << "= operator" << endl;
    }

    ~Teest() {
        cout << "Destructed" << endl;
    }

    void pp() {
        cout << "print " << c << endl;
    }

    int a;

    static int c;

};

int Teest::c = 0;

Teest go() {
    Teest t;
    return t;
}


int main() {
    ios::sync_with_stdio(0);

    int c;
    Teest t = go();
    t.a = 3;
    cout << t.a << endl;
    getchar();
    return 0;
}

The output of the above code is:

Constructed 1;
3
Gabriel Martins
  • 179
  • 1
  • 6
  • 5
    Return value optimization? https://en.wikipedia.org/wiki/Copy_elision#Return_value_optimization – fas May 08 '20 at 04:16
  • What compiler do you use? I checked out your program in MSVC and the destructor IS being called, along with the copy constructor – Suraj S May 08 '20 at 04:16
  • 1
    as @fas said, It may be compiler specific "Depending upon the compiler, and that compiler's settings, the resulting program may display any of the following outputs", as stated in the same page – Suraj S May 08 '20 at 04:19
  • @SurajS I'm running g++ with a basic `g++ -std=c++11 test.cpp -o a` when I do `g++ --version` it says 6.3.0. Is this information relevant or did I just told you useless info about the compiler? I really don't know. – Gabriel Martins May 08 '20 at 13:41
  • @GabrielMartins It's always a good idea, and often useful to tell the compiler and its version that you've used for the program that you're asking about whether you know it will be relevant or not. In this case, compilers happen to behave differently, so it turns out to have been relevant. – eerorika May 08 '20 at 13:49
  • @eerorika That I get. I'm just asking if the info I just gave about the compiler was enough or if there is more that I could've shown – Gabriel Martins May 08 '20 at 14:14

3 Answers3

3

why is Teest class desctructor not called on this code example after go() returns?

Because of the same reason why no copy constructor was called. One object was created, and it was destroyed at the end of main.

The copy from the local variable into the return value was elided. The variable local to go was created directly where the return value would be stored.

This is called (Named) Return Value Optimisation.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • 1
    To anyone wondering, since these are very advanced English and programming terms: "elide" in English = https://www.wordreference.com/definition/elide "to undergo or cause to undergo elision". And Copy Elision = https://en.wikipedia.org/wiki/Copy_elision. – Gabriel Staples May 08 '20 at 04:46
0

@eerorika is right. Elision occurred. If you want to see the destructor get called earlier (for the sake of learning), just create a scope the variable falls out of. Ex:

int main() 
{
    // ...

    // create explicit scope with { }
    {
        Teest t = go();
    } // destructor gets called here

    // rest of main...
    return 0;
}
Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
-3

Destructor is called when you try to delete the instance t inside your main().

Like:

delete t;
Ardent Coder
  • 3,777
  • 9
  • 27
  • 53
hacker315
  • 1,996
  • 2
  • 13
  • 23