C ++ пользовательский оператор удаления не работает? - PullRequest
0 голосов
/ 30 августа 2018

Прежде всего, чтобы сказать, что я испанский и у меня действительно плохой английский, я использовал переводчика с тем, что извиняюсь за то, что выгляжу неграмотным:)


Я годами не играл в c ++ и настолько забыл, что, может быть, у меня возникли сомнения или возможный сбой в языке.

Я написал небольшой код для проверки издержек оператора удаления в c ++ с помощью виртуального деструктора, и обнаружил, что он работает правильно только при первом вызове delete.

Код здесь (это страница, которая позволяет вам писать код онлайн и выполнять его, я тестировал его в visual studio и gcc, и он точно такой же): https://onlinegdb.com/SkiI1dNDQ

Может кто-нибудь сказать мне, почему это происходит? Только первое время работает хорошо, а второе не очень хорошо

Я поместил код здесь и результат, который он дает:

#include <stdio.h>
class Base
{
public:
    virtual ~Base() { printf("~Base\r\n"); }
    void operator delete(void *m) { printf("delete Base\r\n"); }
};
class Derived : public Base
{
public:
    Derived() { x = 1; }
    ~Derived() { printf("~Derived\r\n"); }
    void operator delete(void *m) { printf("delete Derived\r\n"); }
    int x;
};

int main()
{
    Derived *derived = new Derived();
    printf("1) delete derived (%i)\r\n", ((Derived*)derived)->x);
    delete derived;
    printf("2) delete derived (%i)\r\n", ((Derived*)derived)->x);
    delete derived;
    return 0;
}

Результат:

1) delete derived (1)
~Derived
~Base
delete Derived
2) delete derived (1)
~Base
delete Base

Теперь, если мы удалим «виртуальный» класс с именем «Base», все будет идеально, логично всякий раз, когда мы вызываем удаление с помощью «Derived» (код готов удалить виртуальный, и ничего не выходит из строя). Чтобы выполнить это: https://onlinegdb.com/SkXkgdVP7

Спасибо

1 Ответ

0 голосов
/ 30 августа 2018
Derived *derived = new Derived();
printf("1) delete derived (%i)\r\n", ((Derived*)derived)->x);
delete derived;
printf("2) delete derived (%i)\r\n", ((Derived*)derived)->x);
delete derived;

Приведенный выше код неверен и вызывает неопределенное поведение. Вы можете удалить объект только один раз; выше вы (пытаетесь) удалить один и тот же объект дважды. Проблема в том, что после первого вызова delete derived теперь является висящим указателем (т.е. он больше не указывает на действительный объект), и попытка разыменовать его каким-либо образом (включая вызов delete) является ошибкой. ).

...