C++: Optimizing out destructor call

前端 未结 2 1556
刺人心
刺人心 2021-01-29 13:31

There is a little code example here:

struct Data {
};

struct Init {
    Data *m_data;

    Init() : m_data(new Data) { }
    ~Init() {
        delete m_data;
           


        
相关标签:
2条回答
  • 2021-01-29 13:50
    void callInitA() {
        Init x;
        somefunction(x); // calls the "const Init &" constructor
    }
    

    The destruction of x cannot be optimized away, regardless of the contents of Init. Doing so would violate the design of the language.

    It's not just a matter of whether Init contains resources or not. Init x, like all objects, will allocate space on the stack that later needs to be cleaned up, as an implicit (not part of code that you yourself write) part of the destructor. It's impossible to avoid.

    If the intention is for x to be an object that somefunction can call without having to repeatedly create and delete references to x, you should be handling it like this:

    void callInitA(Init & x) { //Or Init const& x
        somefunction(x); // calls the "const Init &" constructor
    }
    

    A few other notes:

    • Make sure you implement the Rule of Five (sometimes known as Rule of Three) on any object that owns resources.
    • You might consider wrapping all pointers inside std::unique_ptr, as it doesn't seem like you need functionality beyond what std::unique_ptr offers.
    0 讨论(0)
  • 2021-01-29 13:50

    Your m_initType actually distinguishes between two kinds of Objects - those which own their memory and those which don't. Also, you mention that actually there are many kinds of Objects which can be initialized with all sorts of inputs; so actually there are all sorts of Objects. That would suggest Object should better be some abstract base class. Now, that wouldn't speed anything up or avoid destructor calls, but it might make your design more reasonable. Or maybe Object could be an std::variant (new in C++17, you can read up on it).

    But then, you say that temporary Objects are "used frequently". So perhaps you should go another way: In your example, suppose you had

    template <bool Owning> class Object;
    

    which you would then specialize for the non-owning case, with only a const Init& constructor and default destruction, and the owning case, with only an Init&& constructor (considering the two you mentioned) and a destructor which deletes. This would mean templatizing the code that uses Object, which many mean larger code size, as well as having to know what kind of Objects you pass in; but if would avoid the condition check if that really bugs you so much.

    I'd like to decrease code size

    I kind of doubt that you do. Are you writing code for an embedded system? In that case it's kind of strange you use lots of temporary Objects which are sort-of polymorphic.

    0 讨论(0)
提交回复
热议问题