虽然这应该是一个微不足道的问题,但到目前为止,我还是找不到答案。在APIs中,有许多函数将指针和指向指针的指针作为参数。如何使用正确的智能指针作为C API的参数。
下面是一个我想转换为使用std::unique_ptr的示例:
FMOD_SYSTEM* system = nullptr;
result = FMOD_System_Create(&system); // Create the main system object
FMOD_SOUND* musicStream;
result = FMOD_System_CreateSound(system,
musicStreamPath,
FMOD_CREATESTREAM,
nullptr,
&musicStream);参考资料:创建 CreateSound
我开始将智能指针声明为:
std::unique_ptr<FMOD_SYSTEM> system = nullptr;
std::unique_ptr<FMOD_SOUND> musicStream = nullptr;如果我使用.get(),下面是编译器错误:
不能将参数'5‘的'std::unique_ptr::pointer {aka FMOD_SOUND*}’转换为'FMOD_SOUND**‘到'FMOD_RESULT FMOD_System_CreateSound(FMOD_SYSTEM*,const char*,FMOD_MODE,FMOD_CREATESOUNDEXINFO*,FMOD_SOUND**)’musicStream.get(); ^
发布于 2014-12-28 22:47:51
您的问题在于,can希望您将指针的地址传递给FMOD_SYSTEM,以便API可以用结果填充该指针--也就是说,它将FMOD_SYSTEM*作为输出参数。
在C++中,这样做的惯用方法是将引用传递给(smart?)指向FMOD_SYSTEM的指针,即C位于
FMOD_RESULT FMOD_System_Create(FMOD_SYSTEM **system);
FMOD_SYSTEM *system;
result = FMOD_System_Create(&system);C++ API将是
FMOD_RESULT FMOD_System_Create(std::unique_ptr<FMOD_SYSTEM> &system);
std::unique_ptr<FMOD_SYSTEM> system;
result = FMOD_System_Create(system);但是,这个C++ API有一个很大的问题!问题是,创建一个FMOD_SYSTEM并将其封装在一个unique_ptr中是不同的问题,不应该像这样混在一起。例如,如果我在线程处理方面做了一些聪明的事情,并且真的需要由shared_ptr而不是简单的unique_ptr来管理我的unique_ptr,该怎么办?我必须创建一个unique_ptr作为out参数传递,然后在std::move之后将其转换为一个shared_ptr?这既丑陋又(微观)低效。
std::unique_ptr<FMOD_SYSTEM> fake_system;
result = FMOD_System_Create(fake_system);
std::shared_ptr<FMOD_SYSTEM> system(std::move(fake_system));答案是要认识到问题的根源在于参数本身,而解决方案是值语义。我们想要编写的惯用C++语法是
auto system = std::make_unique<fmod_system>();获得这种语法的方法是将C的原始指针封装在值类中:
class fmod_system {
FMOD_SYSTEM *ptr;
fmod_system() {
auto result = FMOD_System_Create(&ptr);
if (result != FMOD_OK) {
ptr = nullptr;
throw something;
}
}
fmod_system(fmod_system&&) = default;
fmod_system& operator=(fmod_system&&) = default;
fmod_system(const fmod_system&) = delete;
fmod_system& operator=(const fmod_system&) = delete;
~fmod_system() {
auto result = FMOD_System_Release(ptr);
assert(result == FMOD_OK); // destructors shouldn't throw: use your best judgment here
}
};事实上,在这一点上,我们的调用者可以放弃unique_ptr混淆,只需编写
fmod_system system;除非出于某种原因他们真的需要额外的一层指针语义。
发布于 2014-12-29 10:01:35
总的来说,我不认为将Class与智能指针混合是个好主意,更好的方法是按照Quuxplusone的建议将Class封装在C++类中。
但是,要回答您的问题,我能想到的“最干净的”(但仍然是丑陋的方法)是在创建对象之后,将原始指针传递给带有自定义删除器的智能指针。
struct FMOD_SYSTEM_Deleter {
void operator()(FMOD_SYSTEM* sys) {
if (sys != nullptr) {
FMOD_System_Release(sys);
}
}
}
FMOD_SYSTEM* tsys = nullptr;
result = FMOD_System_Create(&tsys);
std::unique_ptr<FMOD_SYSTEM,FMOD_SYSTEM_Deleter> system(tsys);发布于 2014-12-28 23:44:36
简单的答案是: C++智能指针用于使用new和delete创建的自分配对象。它们不是为指向对象的指针而构建的,这些对象是由第三方C样式API函数内部创建的,需要由另一个C样式API函数发布。在您的情况下,您必须调用System::release而不是delete,因此使用智能指针可能会造成很大的问题。
你有三种可能性:
https://stackoverflow.com/questions/27680981
复制相似问题