Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Order of static destructors

Tags:

c++

If a class Foo has a static member variable Bar, I would expect Bar's destructor to run only after the last instance of Foo's destructor runs. This doesn't happen with the code snippet below (gcc 6.3, clang 3.8):

#include <memory>
#include <iostream>

class Foo;
static std::unique_ptr<Foo> foo;

struct Bar {
    Bar() {
        std::cout << "Bar()" << std::endl;
    }

    ~Bar() {
        std::cout << "~Bar()" << std::endl;
    }
};

struct Foo {
    Foo() {
        std::cout << "Foo()" << std::endl;
    }

    ~Foo() {
        std::cout << "~Foo()" << std::endl;
    }

    static Bar bar;
};
Bar Foo::bar;

int main(int argc, char **argv) {
    foo = std::make_unique<Foo>();
}

Outputs:

Bar()
Foo()
~Bar()
~Foo()

Why is the order of destruction not the reverse of construction here? If ~Foo() uses Foo::bar this is a use after delete.

like image 240
rthur Avatar asked Nov 23 '17 14:11

rthur


People also ask

What is static destructor?

Static destructors are executed one by one in reverse order to the order of corresponding classes definition. Static destructors are always executed after software entry point and always after constructors of all global objects.

How do you destroy a static object in C++?

Static objects are declared with the keyword static. They are initialized only once and stored in the static storage area. The static objects are only destroyed when the program terminates i.e. they live until program termination.

Can destructor be static C++?

Destructors cannot be declared const , volatile , const volatile or static . A destructor can be declared virtual or pure virtual . If no user-defined destructor exists for a class and one is needed, the compiler implicitly declares a destructor.

What are static objects C++?

Static object is an object that persists from the time it's constructed until the end of the program. So, stack and heap objects are excluded. But global objects, objects at namespace scope, objects declared static inside classes/functions, and objects declared at file scope are included in static objects.


2 Answers

In C++ the objects are constructed in order of occurrence and destructed in the reverse order. First comes foo construction, then bar construction then main is executed then bar is destructed and then foo. This is the behavior you are seeing. The switch appears because the constructor of foo doesn't construct a Foo, it constructs an empty unique_ptr, so you don't get to see Foo() in the output. Then bar is constructed with the output and in main you create the actual Foo after foo has long been constructed.

like image 163
nwp Avatar answered Sep 23 '22 23:09

nwp


I would expect Bar's destructor to run only after the last instance of Foo's destructor runs.

No, as a static data member, Foo::bar is independent of any instances of Foo.

And for the code you showed,

static std::unique_ptr<Foo> foo; // no Foo created here

Bar Foo::bar; // Foo::bar is initialized before main(), => "Bar()"

int main(int argc, char **argv) {
    foo = std::make_unique<Foo>(); // an instance of Foo is created, => "Foo()"
} 

// objects are destroyed in the reverse order how they're declared
// Foo::bar is defined after foo, so it's destroyed at first => "~Bar()"
// foo is destroyed; the instance of Foo managed by it is destroyed too => "~Foo()"
like image 36
songyuanyao Avatar answered Sep 25 '22 23:09

songyuanyao