При использовании «размещения нового» предлагается явно вызывать конструктор и деструктор.
Я так не думаю. Он скажет, что вам нужно явно вызвать деструктор.
В этом случае объекты, инициализированные в секции инициализатора класса, также будут правильно построены?
Помимо предоставления памяти, все остальные аспекты размещения new такие же, как обычные new. Поэтому вместо динамического выделения памяти он просто использует предоставленный указатель.
То же самое и с явным вызовом деструктора?
Вы можете (если вы ничего не чувствуете) явно вызывать деструктор для любого объекта. Он будет вызывать пользовательский (или сгенерированный компилятором) деструктор класса как обычно. Причина, по которой вам нужно явно сделать это для объектов, созданных с помощью размещения new, заключается в том, что вы можете вызвать delete для этих объектов. Это связано с тем, что delete предполагает, что объект был создан в динамически выделенной памяти, и пытается повторно выполнить эту память после вызова деструктора.
Правильно ли уничтожены объекты-члены?
Да.
Если мы думаем о новом, как это:
// not real code
template<class T> T* new(void* location = NULL) (ArgumentsForT)
{
// If you do not provide location (normal usage)
// then we allocate some memory for you.
if (location == NULL)
{ location = malloc(sizeof(T)); // Use of malloc() is just an example
}
((T*)location)->Constructor(ArgumentsForT);
return (T*)location;
}
Таким образом, размещение нового будет работать так же, как обычное новое.
Глядя на звонок для удаления
template<typename T> void delete(T* obj)
{
if (obj != NULL)
{
obj->~T();
free(obj);
}
}
Проблема здесь в том, что delete не может определить, была ли память выделена новой или была ли выделена память пользователем и передана в новую (размещение новой). Так что это всегда звонит бесплатно в память. Если вы использовали новое размещение, то у вас может не быть динамического выделения памяти (или память все еще используется для чего-то другого).
char x[sizeof(T)]; // don't do this (memory may not be aligned correctly).
T* obj = new (x) T();
delete obj; // FAIL. The memory was not dynamically allocated.
// Delete will try and re-claim this memory for re-yse
// Even if the memory is local.
// This is why on placement new you need to call the destructor
obj->~T();