Mixing operator new[] and placement new with ordinary delete[]

前端 未结 5 2085
悲&欢浪女
悲&欢浪女 2020-12-18 20:10

Just out of curiosity, is the following legal?

X* p = static_cast(operator new[](3 * sizeof(X)));
new(p + 0) X();
new(p + 1) X();
new(p + 2) X();

         


        
5条回答
  •  情话喂你
    2020-12-18 20:29

    Correct would be:

    X* p = static_cast(new char[3 * sizeof(X)]);
    // ...
    delete[] static_cast(p);
    

    or

    X* p = static_cast(operator new[](3 * sizeof(X)));
    // ...
    operator delete[](p);
    

    The type of the array delete expression has to match the new expression exactly.


    The first example is UB because section 5.3.5 ([expr.delete]) says

    In the first alternative (delete object), if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.


    My corrected version is ok because (section 3.9 [basic.life]):

    A program may end the lifetime of any object by reusing the storage which the object occupies or by explicitly calling the destructor for an object of a class type with a non-trivial destructor. For an object of a class type with a non-trivial destructor, the program is not required to call the destructor explicitly before the storage which the object occupies is reused or released; however, if there is no explicit call to the destructor or if a delete-expression (5.3.5) is not used to release the storage, the destructor shall not be implicitly called and any program that depends on the side effects produced by the destructor has undefined behavior.


    The second example is not allowed iff X has a non-trivial destructor because (also 3.9 [basic.life]):

    Before the lifetime of an object has started but after the storage which the object will occupy has been allocated 38 or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that refers to the storage location where the object will be or was located may be used but only in limited ways. For an object under construction or destruction, see 12.7. Otherwise, such a pointer refers to allocated storage (3.7.4.2), and using the pointer as if the pointer were of type void*, is well-defined. Such a pointer may be dereferenced but the resulting lvalue may only be used in limited ways, as described below.

    The program has undefined behavior if:

    • the object will be or was of a class type with a non-trivial destructor and the pointer is used as the operand of a delete-expression,

提交回复
热议问题