Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11's deleted destructor in derived class

class B {
    int i;
public:
    B(int param) : i(param) {}
    ~B() = delete;
};
class D : public B {
    int i2;
public:
    D(int p1, int p2) : B(p1), i2(p2) {}
    ~D() = delete;
};

int main() {
    B* instance = new D(1,2);
    return 0;
}

cl test.cpp:

Microsoft (R) C/C++ Optimizing Compiler Version 18.00.31101 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.cpp
test.cpp(11) : error C2280: 'B::~B(void)' : attempting to reference a deleted function
    test.cpp(6) : see declaration of 'B::~B'

(There is one emply line above the code, so these are one off. sorry)

I have some special classes(one base and many derived) that for performance reasons are always allocated in a stack like memory arena. They don't get any destructor calls(and by design they don't need to). This can be bad if some programmer after me decide that he really needs to put a vector inside.(memory leaks, these classes are spawned in large numbers and live a few function calls, ouch)

What I tried is using C++11 deleted destructors. My questions are:

  • Why is this not working?
  • Any better ideas how to forbid destructors or non-PODs inside the class?
like image 838
Nickie Avatar asked Dec 11 '22 01:12

Nickie


1 Answers

Why is this not working?

§12.6.2 [class.base.init]/p10:

In a non-delegating constructor, the destructor for each potentially constructed subobject of class type is potentially invoked (12.4). [ Note: This provision ensures that destructors can be called for fully-constructed sub-objects in case an exception is thrown (15.2). — end note ]

§12.4 [class.dtor]/p11:

[...] A program is ill-formed if a destructor that is potentially invoked is deleted or not accessible from the context of the invocation.

If an exception is thrown during a construction of any of subobjects, a compiler calls the destructors of already constructed base classes and data members, therefore the constructor of D requires a non-deleted, accessible destructor of B.

Any better ideas how to forbid destructors or non-PODs inside the class?

In your case making the destructors protected ones should work instead:

class B {
    int i;
public:
    B(int param) : i(param) {}
protected:
    ~B() {}
};
class D : public B {
    int i2;
public:
    D(int p1, int p2) : B(p1), i2(p2) {}
protected:
    ~D() {}
};
like image 113
Piotr Skotnicki Avatar answered Dec 26 '22 15:12

Piotr Skotnicki