当我将原始指针更改为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:Usersnot_bjarneCodeBlocksMinGWlibgccx86_64-w64-mingw328.1.0includec++bitsunique_ptr.h|831|错误:不完整类型'struct _Mix_Music'的无效使用”

代码块将我指向unique_ptr.h,我显然没有试图“修复”。

回答

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

std::unique_ptr可用于此目的,但需要自定义删除器。默认删除器将调用delete,此处不应执行此操作。您看到的错误是因为不完整而格式错误delete p;(其中p有 type Mix_Music*)。您必须确保自定义删除程序调用Mix_FreeMusic. 您可以在此处查看如何使用自定义删除器:如何使用带有 std::unique_ptr 成员的自定义删除器?


以上是当我将原始指针更改为unique_pointer时,为什么会出现“无效使用不完整类型”错误?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>