C++ disable destructors for static variables

只愿长相守 提交于 2019-12-05 16:18:22

The answer is by creating a wrapper:

template<class T>
class StaticWrapper
{
public:
    using pointer = typename std::add_pointer<T>::type;

    template<class... Args>
    StaticWrapper(Args && ...args)
    {
        new (mData) T(std::forward<Args>(args)...);
    }

    pointer operator ->()
    {
        return reinterpret_cast<pointer>(mData);
    }

private:
    alignas(T) int8_t mData[sizeof(T)];
};

This wrapper can be used to wrap classes which destructor should not be called:

struct A
{
    int i;
};

static StaticWrapper<A> a;
a->i = 1;

The way it works is - we reserve (statically) some memory big enough to contain the object with proper alignment. Then we use an in-place new operator to create the actual object in the reserved memory and forward potential arguments to its constructor. We can access the object from our wrapper using operator ->. The destructor will never be called because, from the compiler perspective, there is no object of class T anywhere - only an array of bytes. We just use those bytes to hold the object.

In a bare-metal embedded system you normally have access to the run-time start-up code (usually in assembler); this code performs global static initialisation including calling constructors before calling main(). It also determines what happens if main() terminates; that is where static destructors will be called - this code can be removed (if it even exists already), so that the destructor is not explicitly called on termination - this may allow linker optimisation to then remove the unused code.

You should check the map file to determine whether the destructor is included in the build rather than looking at the compiler assembler output - the compiler has no option but to generate the code since it does not know whether it will be externally referenced or not. You may need to set specific linker options to remove unused code.

Just use a reference to a heap allocated variable. It will leak, but I guess that's what you want.

static A& a = *(new A);

A simple solution is to use placement new - instantiating the objects on appropriately sized static arrays. You can also use a reference variable to access the objects via the instance rather than the pointer.

#include <new>

static char mem_for_a[sizeof(A)] ;
static A* aptr = new(mem_for_a) A ;
static A& a = *aptr ;

static char mem_for_b[sizeof(A)] ;
static A* bptr = new(mem_for_b) A ;
static A& b = *bptr ;

In placement objects, the destructor must be explicitly called so you have complete control over whether and when it is called.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!