【问题标题】:Why I'm getting "invalid use of incomplete type" error when I change raw pointer to unique_pointer?当我将原始指针更改为 unique_pointer 时,为什么会出现“不完整类型的无效使用”错误?
【发布时间】:2021-05-02 16:18:20
【问题描述】:

我正在用 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\8.1.0\include\c++\bits\unique_ptr.h|831|错误: 不完整类型 'struct _Mix_Music' 的使用无效"

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

【问题讨论】:

  • 您应该告诉我们该文件第 831 行的详细信息。这可能会回答发生了什么的问题。
  • 当然,它是{ return unique_ptr&lt;_Tp&gt;(new _Tp(std::forward&lt;_Args&gt;(__args)...)); }。但问题似乎正是布赖恩所说的。

标签: c++ pointers sdl-2 smart-pointers


【解决方案1】:

似乎Mix_Music 是一个不完整的类型,释放Mix_Music 对象的正确方法是调用Mix_FreeMusic 函数。您不能像处理 C++ 对象那样处理它,即使用deletedelete 会尝试调用析构函数(在这种情况下不能这样做,因为这里的类型不完整)并假设对象是由new 分配的,并将内存返回到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?

【讨论】:

    猜你喜欢
    • 2011-12-21
    • 2021-11-08
    • 2011-09-12
    • 1970-01-01
    • 2013-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-07
    相关资源
    最近更新 更多