Date: Tue, 13 Aug 2019 17:04:04 +0000 (UTC)
One approach to the static initialization order problem looks like:
A & a1()
{
static A a;
return(a);
}
The problem is that, if A had a non-trivial destructor, the static order destruction problem could still cause undefined behavior. A solution to this, avoiding the call to A::~A, is:
A & a2()
{
static A* a(new A);
return(*a);
}
This template, no_destructor, avoids the destructor call without requiring an unnecessary dynamic allocation:
#include <utility>
#include <new>
template <typename T>
class no_destructor
{
public:
template <typename ... Args>
no_destructor(Args && ... args)
{
new (payload) T(std::forward<Args>(args)...);
}
T & operator () () { return(*reinterpret_cast<T *>(payload)); }
private:
alignas(T) char payload[sizeof(T)];
};
A & a3()
{
static no_destructor<A> a;
return(a());
}
https://godbolt.org/z/cGSXRy
A & a1()
{
static A a;
return(a);
}
The problem is that, if A had a non-trivial destructor, the static order destruction problem could still cause undefined behavior. A solution to this, avoiding the call to A::~A, is:
A & a2()
{
static A* a(new A);
return(*a);
}
This template, no_destructor, avoids the destructor call without requiring an unnecessary dynamic allocation:
#include <utility>
#include <new>
template <typename T>
class no_destructor
{
public:
template <typename ... Args>
no_destructor(Args && ... args)
{
new (payload) T(std::forward<Args>(args)...);
}
T & operator () () { return(*reinterpret_cast<T *>(payload)); }
private:
alignas(T) char payload[sizeof(T)];
};
A & a3()
{
static no_destructor<A> a;
return(a());
}
https://godbolt.org/z/cGSXRy
Received on 2019-08-13 12:06:34