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.
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.
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.
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.
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.
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.
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()"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With