为什么我将原始指针更改为 unique_pointer 时出现 "invalid use of incomplete type" 错误?
Why I'm getting "invalid use of incomplete type" error when I change raw pointer to unique_pointer?
我正在用 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:\Users\not_bjarne\CodeBlocks\MinGW\lib\gcc\x86_64-w64-mingw32.1.0\include\c++\bits\unique_ptr.h|831|error:
invalid use of incomplete type 'struct _Mix_Music'"
代码块将我指向 unique_ptr.h
,我显然没有尝试“修复”。
似乎 Mix_Music
是一个不完整的类型,释放 Mix_Music
对象的正确方法是调用 Mix_FreeMusic
函数。您不能像处理 C++ 对象那样处理它,即使用 delete
。 delete
将尝试调用析构函数(在此上下文中无法完成,因为此处的类型不完整)并假定该对象是由 new
和 return 内存分配给new
从中获取它的同一个池。 SDL 分配对象的方式是一个实现细节,因此您也必须让 SDL 释放对象本身,以确保正确完成。
std::unique_ptr
可用于此目的,但需要自定义删除器。默认的删除器会调用 delete
,这里不应该这样做。您看到的错误是因为 delete p;
由于不完整而格式错误(其中 p
的类型为 Mix_Music*
)。您必须确保自定义删除器调用 Mix_FreeMusic
。您可以在此处查看如何使用自定义删除器:How do I use a custom deleter with a std::unique_ptr member?
我正在用 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:\Users\not_bjarne\CodeBlocks\MinGW\lib\gcc\x86_64-w64-mingw32.1.0\include\c++\bits\unique_ptr.h|831|error: invalid use of incomplete type 'struct _Mix_Music'"
代码块将我指向 unique_ptr.h
,我显然没有尝试“修复”。
似乎 Mix_Music
是一个不完整的类型,释放 Mix_Music
对象的正确方法是调用 Mix_FreeMusic
函数。您不能像处理 C++ 对象那样处理它,即使用 delete
。 delete
将尝试调用析构函数(在此上下文中无法完成,因为此处的类型不完整)并假定该对象是由 new
和 return 内存分配给new
从中获取它的同一个池。 SDL 分配对象的方式是一个实现细节,因此您也必须让 SDL 释放对象本身,以确保正确完成。
std::unique_ptr
可用于此目的,但需要自定义删除器。默认的删除器会调用 delete
,这里不应该这样做。您看到的错误是因为 delete p;
由于不完整而格式错误(其中 p
的类型为 Mix_Music*
)。您必须确保自定义删除器调用 Mix_FreeMusic
。您可以在此处查看如何使用自定义删除器:How do I use a custom deleter with a std::unique_ptr member?