2015-12-03 6 views
4

Я пищу от класса STFT. Составляет просто отлично с этим в заголовке:Почему «ошибка: неверное приложение« sizeof »для неполного типа с использованием unique_ptr» исправлено путем добавления пустого деструктора?

class STFT; // pimpl off to prevent point name clash 

class Whatever 
{ 
private: 
    STFT* stft; 

и это в реализации:

#include "STFT.h" 
Whatever::Whatever() : stft(new STFT()) { 
// blah blah 
} 

Whatever::~Whatever() { 
    delete stft; // pure evil 
} 

Однако переход на std::unique_ptr<STFT> stft; над сырым указателем в заголовке, и удаление деструктор, я получаю

error: invalid application of 'sizeof' to an incomplete type 'STFT' static_assert(sizeof(_Tp) > 0, "default_delete can not delete incomplete type");

Но если я просто поставлю пустой деструктор Whatever::~Whatever(){}, тогда он компилируется в порядке. Это меня полностью застопорило. Пожалуйста, наполните меня тем, что делает этот бессмысленный деструктор для меня.

+0

Протестировано без ошибок только сейчас:/ – learnvst

ответ

8

Так что, если мы идем в cppreference документа для std::unique_ptr:

std::unique_ptr may be constructed for an incomplete type T, such as to facilitate the use as a handle in the Pimpl idiom. If the default deleter is used, T must be complete at the point in code where the deleter is invoked, which happens in the destructor, move assignment operator, and reset member function of std::unique_ptr. (Conversely, std::shared_ptr can't be constructed from a raw pointer to incomplete type, but can be destroyed where T is incomplete).

Мы можем видеть в коде ниже:

#include <memory> 

class STFT; // pimpl off to prevent point name clash 

class Whatever 
{ 
    public: 
    ~Whatever() ; 
    private: 
     std::unique_ptr<STFT> stft; 
} ; 

//class STFT{}; 

Whatever::~Whatever() {} 

int main(){} 

требования не выполняются, когда Defintion из STFT комментируется перед тем деструктор Whatever определен, поскольку для этого требуется деструктор для stft, который, в свою очередь, требует, чтобы STFT был полным.

Так что вполне вероятно, что в вашем реализации файла STFT завершается, когда Whatever::~Whatever() определено, но в противном случае дефолте один создается без STFT завершения.

3

Моей обычная идиома для предоставления таких деструкторов является

Whatever::~Whatever() = default; 

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

+3

Использование этого синтаксиса дает такую ​​же ошибку. Мне нужно явно объявить пустой dtor. – learnvst

+0

Это зависит **, где ** вы его положили. Если вы поместите его в заголовок, где 'STFT' является неполным, то это так же плохо, как позволить компилятору сгенерировать его там, где это необходимо. Он должен быть в файле реализации после '#include ', где все указанные типы будут завершены. Если бы это не сработало, я бы не использовал его сам. –

+0

Ahhhh. ОК. Это работает – learnvst

 Смежные вопросы

  • Нет связанных вопросов^_^