Я искал для повторного использования выделенного пространства в базовом классе из этого указателя, и C ++ Standard не одобряет. Однако формулировка стандарта кажется неверной. Он ставит условие «и перед тем, как хранилище, в котором занят объект, используется повторно или освобождается», но оно явно используется повторно в своем фрагменте кода. Где я ошибаюсь?
До того, как началось время жизни объекта, но после того, как было выделено хранилище, которое будет занимать объект41, или после того, как истек срок жизни объекта и до того, как хранилище, которое занимал объект, используется повторно или освобождается, любой указатель, который представляет адрес места хранения, где объект будет или был расположен, может использоваться, но только ограниченным образом. О строящемся или разрушаемом объекте см. [Class.cdtor]. В противном случае такой указатель ссылается на выделенное хранилище ([basic.stc.dynamic.deallocation]), и использование указателя, как если бы указатель имел тип void *, является четко определенным. Переадресация через такой указатель разрешена, но результирующее lvalue может использоваться только ограниченным образом, как описано ниже. Программа имеет неопределенное поведение, если:
(6.1)
объект будет или имел тип класса с нетривиальным деструктором, а указатель используется в качестве операнда выражения удаления
(6,2)
указатель используется для доступа к нестатическому члену данных или для вызова нестатической функции-члена объекта, или
(6,3)
указатель неявно преобразуется ([conv.ptr]) в указатель на виртуальный базовый класс или
(6.4)
указатель используется как операнд static_cast, за исключением случаев, когда преобразование является указателем на cv void или указателем на cv void, а затем на указатель на cv char, cv unsigned char или cv std :: byte ([ cstddef.syn]) или
(6,5)
указатель используется в качестве операнда dynamic_cast.
[Пример:
#include <cstdlib>
struct B {
virtual void f();
void mutate();
virtual ~B();
};
struct D1 : B { void f(); };
struct D2 : B { void f(); };
/* RELEVANT PART STARTS */ void B::mutate() {
new (this) D2; // reuses storage — ends the lifetime of *this
f(); // undefined behavior
/* RELEVANT PART ENDS */
... = this; // OK, this points to valid memory
}
void g() {
void* p = std::malloc(sizeof(D1) + sizeof(D2));
B* pb = new (p) D1;
pb->mutate();
*pb; // OK: pb points to valid memory
void* q = pb; // OK: pb points to valid memory
pb->f(); // undefined behavior, lifetime of *pb has ended
}