виртуальный деструктор не работает с массивом

Я нашел этот код на веб-сайте.

#include <iostream>

using namespace std;

struct Base
{
    Base() { cout << "Base" << " "; }
    virtual ~Base() { cout << "~Base" << endl; }

    int i;
};
struct Der : public Base
{
    Der() { cout << "Der" << endl; }
    virtual ~Der() { cout << "~Der" << " "; }

    int it[10]; // sizeof(Base) != sizeof(Der)
};

int main()
{
    Base *bp = new Der;
    Base *bq = new Der[5];

    delete    bp;
    delete [] bq;   // this causes runtime error
}

почему происходит крах?


person Ruggero Turra    schedule 13.10.2011    source источник
comment
возможный дубликат полиморфизма и указателей на массивы   -  person NPE    schedule 13.10.2011
comment
также stackoverflow.com/questions/1043402/why-this-code-crashes   -  person NPE    schedule 13.10.2011
comment
Просто используйте std::vector‹Base*› вместо массива...   -  person k06a    schedule 13.10.2011
comment
Или std::array‹Base*› из C++0x...   -  person k06a    schedule 13.10.2011


Ответы (1)


Base *bq = new Der[5];
delete [] bq;   // this causes runtime error

Причина в том, что массивы не обрабатываются полиморфно. Таким образом, в приведенном выше коде оператор delete вызывает неопределенное поведение.

§5.3.5/3 С++ 03 говорит

В первом варианте (удалить объект), если статический тип операнда отличается от его динамического типа, статический тип должен быть базовым классом динамического типа операнда, а статический тип должен иметь виртуальный деструктор или поведение не определено. . Во втором варианте (удалить массив), если динамический тип удаляемого объекта отличается от его статического типа, поведение не определено.

Вам повезло, что это выдает ошибку времени выполнения, и у вас есть возможность как можно скорее узнать о серьезной ошибке в вашем коде.

person Nawaz    schedule 13.10.2011
comment
И это, кажется, имеет место и в С++ 11. Тот же раздел: 5.3.5/3 - person John Dibling; 13.10.2011