c++ - Is a member function allowed to explicitly call its class destructor -
- does following code have defined behavior ?
- if not, part of code ub , section(s) of standard states ub ?
- if code ub, there [minor] change can fix ?
- if nothing can fix it, other code scheme/pattern used implement same feature ?
class c { public: virtual ~c() {} virtual void switch_me() = 0; }; class c1 : public c { public: c1() : b(true) { std::cout << "c1\n"; } ~c1() { std::cout << "~c1\n"; } private: void switch_me(); bool b; }; class c2 : public c { public: c2() : i(1) { std::cout << "c2\n"; } ~c2() { std::cout << "~c2\n"; } private: void switch_me(); int i; };
void c1::switch_me() { this->~c1(); // lifetime of *this ends here std::cout << "blih\n"; // execute code // not attempt access object new(this) c2(); // create c2 instance in-place } void c2::switch_me() { this->~c2(); // lifetime of *this ends here std::cout << "blah\n"; // execute code... new(this) c1(); // create c1 instance in-place }
class cnt { public: cnt() { new(&storage) c1(); } ~cnt() { (*this)->~c(); } c* operator->() { return reinterpret_cast<c*>(&storage); } private: char storage[std::max(sizeof(c1),sizeof(c2))]; }; int main() { cnt c; c->switch_me(); c->switch_me(); return 0; }
you not have undefined behavior regarding switch_me
function: not access object in way after destruction, , next access happens on new object. might have ub if save pointer , reference c
object returned vy operator->
, use after call switch_me
per 3.8/7:
if, after lifetime of object has ended , before storage object occupied reused or released, new object created @ storage location original object occupied, pointer pointed original object, reference referred original object, or name of original object automatically refer new object and, once lifetime of new object has started, can used manipulate new object, if:
- the storage new object overlays storage location original object occupied, ,
- the new object of same type original object (ignoring top-level cv-qualifiers), ,
- the type of original object not const-qualified, and, if class type, not contain non-static data member type const-qualified or reference type, ,
- the original object derived object (1.8) of type t , new object derived object of type t (that is, not base class subobjects).
you have ub in other place, namely, storage. has weaker alignment object want place in it, , can cause alignment issues. use alignas
keyword specify desired alignment:
alignas(c1) alignas(c2) char storage[std::max(sizeof(c1),sizeof(c2))];
if 2 alignment specifiers applied same declaration, larger used.
Comments
Post a Comment