首先,我想说我完全同意 Dietmar Kühl 和 Mats Petersson 的回答。但是,您还必须考虑到 SDL 是一个纯 C 库,其中大多数 API 函数期望可以拥有大量数据的结构的 C 指针。所以你不应该在堆栈上分配它们(你应该使用 new 运算符在堆上分配它们)。此外,由于 C 语言不包含智能指针,因此您需要使用 std::unique_ptr::get() 来恢复 std::unique_ptr 拥有的 C 指针,然后再将其发送到 SDL API 函数。这可能非常危险,因为您必须确保在 SDL 使用 C 指针时 std::unique_ptr 不会超出范围(与 std::share_ptr 类似的问题)。否则你会得到段错误,因为 std::unique_ptr 将在 SDL 使用它时删除 C 指针。
每当您需要在 C++ 程序中调用纯 C 库时,我建议使用 RAII。主要思想是您创建一个拥有 C 指针并为您调用 SDL API 函数的小型包装类。然后使用类析构函数删除所有 C 指针。
例子:
class SDLAudioWrap {
public:
SDLAudioWrap() { // constructor
// allocate SDL_AudioSpec
}
~SDLAudioWrap() { // destructor
// free SDL_AudioSpec
}
// here you wrap all SDL API functions that involve
// SDL_AudioSpec and that you will use in your program
// It is quite simple
void SDL_do_some_stuff() {
SDL_do_some_stuff(ptr); // original C function
// SDL_do_some_stuff(SDL_AudioSpec* ptr)
}
private:
SDL_AudioSpec* ptr;
}
现在您的程序是异常安全的,并且您不会遇到在 SDL 使用它时让智能指针删除您的 C 指针的可能问题。
更新 1:我忘了提到因为 SDL 是一个 C 库,所以您需要一个自定义删除器类才能使用智能指针正确管理其 C 结构。
具体示例:GSL GNU 科学库。集成例程需要分配一个名为“gsl_integration_workspace”的结构。在这种情况下,您可以使用以下代码来确保您的代码是异常安全的
auto deleter= [](gsl_integration_workspace* ptr) {
gsl_integration_workspace_free(ptr);
};
std::unique_ptr<gsl_integration_workspace, decltype(deleter)> ptr4 (
gsl_integration_workspace_alloc (2000), deleter);
我更喜欢包装类的另一个原因