为什么当我将原始指针更改为unique_pointer时"invalid use of incomplete type"出现错误?



我正在用c++制作一些SDL2包装器。这样的:

/* header file */
#include <SDL_mixer.h>
#include <memory>
class SDL2_Music {
public:
~SDL2_Music() { free(); }
bool loadMusic(const std::string& path);
bool play(int loops = -1);
// more methods
private:
void free();
Mix_Music* music_ = nullptr;
};
/* cpp file */
void SDL2_Music::free() {
if (music_ != nullptr) {
Mix_FreeMusic(music_);
music_ = nullptr;
}
}
bool SDL2_Music::loadMusic(const std::string& path) {
free();
music_ = Mix_LoadMUS(path.c_str()); // this returns a Mix_Music*
if (music_ == nullptr) {
ktp::logSDLError("Mix_LoadMUS");
return false;
}
return true;
}
// more stuff

这工作得很好,但我想摆脱原始指针,所以我也可以摆脱free()方法和dtor调用它(是的,我正在阅读关于0的规则),所以我做了以下更改:

/* header file */
#include <SDL_mixer.h>
#include <memory>
class SDL2_Music {
public:
bool loadMusic(const std::string& path);
bool play(int loops = -1);
// more methods
private:
std::unique_ptr<Mix_Music> music_ = nullptr; 
};
/* cpp file */
bool SDL2_Music::loadMusic(const std::string& path) {
music_ = std::make_unique<Mix_Music>(Mix_LoadMUS(path.c_str()));
if (music_ == nullptr) {
ktp::logSDLError("Mix_LoadMUS");
return false;
}
return true;
}
// more stuff

当我尝试编译(GCC)时,我得到:

"C: not_bjarne CodeBlocks 用户MinGW lib gcc x86_64-w64-mingw32 8.1.0 c++ 位 包括 unique_ptr.h | 831 |错误:无效使用不完整类型"struct _Mix_Music">

和代码块指向unique_ptr.h,我显然没有试图"修复"。

似乎Mix_Music是一个不完整的类型,释放Mix_Music对象的正确方法是调用Mix_FreeMusic函数。您不能像处理c++对象那样处理它,即使用deletedelete将尝试调用析构函数(在这个上下文中不能这样做,因为这里的类型是不完整的),并假设对象是由new分配的,并将内存返回到new获得它的同一个池中。SDL分配对象的方式是一个实现细节,所以你必须让SDL释放对象本身,以确保它被正确地完成。

std::unique_ptr可以用于此目的,但需要自定义删除器。默认的删除器将调用delete,这里不应该这样做。您看到的错误是因为由于不完整,delete p;格式错误(其中p的类型为Mix_Music*)。必须确保自定义删除器调用Mix_FreeMusic。您可以在这里看到如何使用自定义delete:如何使用带有std::unique_ptr成员的自定义delete ?

最新更新