最初に言いたいのは、私はディートマー・キュールとマッツ・ピーターソンの回答に完全に同意するということです。ただし、SDL は純粋な C ライブラリであり、大部分の API 関数が、大量のデータを所有できる構造体の C ポインターを想定していることも考慮する必要があります。そのため、それらをスタックに割り当てるべきではありません (ヒープに割り当てるには new 演算子を使用する必要があります)。さらに、C 言語にはスマート ポインターが含まれていないため、std::unique_ptr::get() を使用して、std::unique_ptr が所有する C ポインターを回復してから、SDL API 関数に送信する必要があります。SDL が C ポインタを使用している間は std::unique_ptr が範囲外にならないようにする必要があるため、これは非常に危険です (std::share_ptr と同様の問題)。そうしないと、SDL が使用している間に std::unique_ptr が C ポインターを削除するため、seg fault が発生します。
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 ポインターを使用しているときにスマート ポインターが 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);
ラッパー クラスを好むもう 1 つの理由