Прямой вызов деструктора в C++

Отсюда код ниже.

class A
{
    int x;
public:
    A() {x = 3;}
};


int main()
{
    void* mem = operator new(sizeof(A));
    A* obj = static_cast<A*>(new(mem)(A));
    std::cout << obj->x << std::endl;
    obj->A::~A();
    std::cout << obj->x << std::endl;
}

Мой первый вопрос: почему я могу напрямую вызвать деструктор A; Мой второй вопрос: почему вывод:

3
3

Объект obj не удаляется после вызова деструктора? Вторые 3 меня смущают.


person Eduard Rostomyan    schedule 11.05.2015    source источник
comment
поскольку это обычная функция, она автоматически вызывается компилятором при выделении памяти (объект выходит за рамки основной функции).   -  person cerkiewny    schedule 11.05.2015


Ответы (1)


Почему я могу вызвать деструктор?

Потому что это общедоступная функция-член, и вы можете вызывать общедоступные функции-члены.

Почему объект не удаляется?

В вашем конкретном случае он все еще существует, потому что A имеет тривиальный деструктор.

Если бы он был нетривиальным, он был бы удален в том смысле, что вам больше не разрешено его использовать. Если вы все равно это сделаете, у вас будет неопределенное поведение.

Для более подробного обсуждения этого прочитайте это.

person Baum mit Augen    schedule 11.05.2015
comment
Это неопределенное поведение? Я так не думаю, было бы, если бы вы удалили объект не после того, как вызвали деструктор... - person cerkiewny; 11.05.2015
comment
@cerkiewny Да, это абсолютно неопределенное поведение. delete вызывает деструктор и освобождает память. В этом случае мы просто делаем первое без второго. - person Barry; 11.05.2015
comment
@cerkiewny Это UB: после вызова деструктора для объекта объект больше не существует, как и переменная-член x. - person Baum mit Augen; 11.05.2015
comment
@BaummitAugen, когда он вызывается, а не когда вы его вызываете. Насколько я понимаю, это обычный метод, но так уж получилось, что компилятор автоматически вводит его вызов при удалении объекта. Если вы собираетесь использовать объект после этого вызова, объект не существует, поэтому его использование приводит к неопределенному поведению, но если вы вызываете деструктор напрямую, объект все еще существует, поэтому вы можете использовать его как обычно... - person cerkiewny; 11.05.2015
comment
@cerkiewny obj->A::~A(); явно вызывает деструктор. Деструктор в значительной степени следует обычному синтаксису функций-членов (см. 12.4.13 в N3797, если вас волнует формальная формулировка). В конце этого выражения объект мертв. Я не совсем понимаю, что вас смущает. Может быть, опубликовать новый вопрос с четкой формулировкой проблемы? - person Baum mit Augen; 11.05.2015
comment
@cerkiewny Память, в которой жил объект, конечно, все еще ваша, если вы об этом говорите. Вы можете создать новый объект типа A в этой памяти, а затем использовать его. Однако исходный объект определенно непригоден для использования. - person Baum mit Augen; 11.05.2015
comment
Это неопределенное поведение по тем же причинам, по которым доступ к неинициализированной памяти всегда является неопределенным поведением: -c" title="почему используется неопределенное поведение неинициализированной переменной в c">stackoverflow.com/questions/11962457/ - person Sebastian; 11.05.2015
comment
Вкратце: некоторые архитектуры могут повторно инициализировать значение x внутри dtor значением ловушки. - person Sebastian; 11.05.2015