std :: unique_ptr базового класса, содержащего ссылку на производный класс, не показывает предупреждение в компиляторе gcc, в то время как голый указатель показывает это. Зачем? - PullRequest
34 голосов
/ 25 апреля 2019

У меня есть иерархия базового класса и производного класса. Базовый класс имеет одну виртуальную функцию, которая переопределяется производным классом.

class Base
{  
public:  
    ~Base();    
    virtual void other_functionality() = 0;  
};

class Derived : public Base
{  
public:  
    ~Derived ();    
    void other_functionality() {//some code};  
};

Теперь, если я сделаю так:

int main()
{
Base * P = new Derived ();
delete p;
return 0;
}

выдает ошибку:
удаление объекта типа полиморфного класса, который имеет не виртуальный деструктор.

Но с unique_ptr он проходит без предупреждения.

int main()
{
 std::unique_ptr<Base> p;
 p.reset(new Derived ());

return 0;
}

Я знаю, использую ли я виртуальный деструктор. Предупреждение с голым указателем будет решено. Но остается вопрос - почему отсутствие виртуального деструктора показывает проблему с голым указателем, а не с unique_ptr.

Ответы [ 2 ]

40 голосов
/ 25 апреля 2019

Ну, во-первых, удаление производного объекта через базовый указатель, когда базовый класс не имеет виртуального деструктора, является неопределенным поведением.Компиляторы не обязаны диагностировать неопределенное поведение…

При этом причина, по которой это предупреждение не появляется при использовании std::unique_ptr, наиболее вероятна из-за того, что GCC не сообщает о предупреждениях, которыепоявляются в системных заголовках .

21 голосов
/ 25 апреля 2019

Я не могу найти ссылку, но я видел обсуждение этого в сети, в базе данных ошибок GCC.

Предупреждение выдается на фактическое выражение delete. В случае unique_ptr, delete вызывается внутри системного заголовочного файла.

Согласно обсуждению в этом отчете об ошибках, реализация системных библиотек C ++ требует всевозможных компромиссов, которые приводят к различным предупреждениям. Поэтому предупреждения ограничены внутри системных заголовков. Вот почему вы не увидите ожидаемого предупреждения.

Обновление: и вот оно, прямо изо рта лошади:

https://gcc.gnu.org/onlinedocs/cpp/System-Headers.html

Заголовочные файлы, объявляющие интерфейсы к операционной системе и библиотекам времени выполнения, часто не могут быть записаны в строго соответствующем C. Поэтому GCC придает коду, найденному в системных заголовках, специальную обработку. Все предупреждения, кроме предупреждений, генерируемых «#warning» (см. «Диагностика»), подавляются, пока GCC обрабатывает системный заголовок.

...