C RAII クラスの OpenGL オブジェクト: コピー後に動作が停止する理由
C では、RAII (リソースの取得は初期化) を利用するのが一般的です) オブジェクトが破棄されたときに自動的にクリーンアップされるようにします。ただし、OpenGL オブジェクトを扱う場合、RAII パターンがオブジェクトの使用にどのような影響を与えるかを理解することが重要です。
OpenGL バッファ オブジェクトをカプセル化する次のクラスを考えてみましょう。
class BufferObject { private: GLuint buff_; public: BufferObject() { glGenBuffers(1, &buff_); } ~BufferObject() { glDeleteBuffers(1, &buff_); }
最初は、このクラス正しく機能しているようです。ただし、特定の操作を実行するときに問題が発生します。
vector<BufferObject> bufVec; { BufferObject some_buffer; // Initialize some_buffer; bufVec.push_back(some_buffer); } bufVec.back(); // buffer doesn't work. BufferObject InitBuffer() { BufferObject buff; // Do stuff with `buff` return buff; } auto buff = InitBuffer(); // Returned buffer doesn't work.
push_back または return ステートメントを介してクラスをコピーすると、予期しない OpenGL エラーが発生します。その理由を理解するには、RAII の仕組みを詳しく調べる必要があります。
オブジェクトがコピーされると、デフォルトのコピー コンストラクターが呼び出されます (コピー コンストラクターが存在すると仮定します)。この場合、デフォルトのコピー コンストラクターは単にメンバー変数をコピーします。ただし、このコピーには、各オブジェクトに固有の OpenGL オブジェクト ハンドル (buff_) が含まれています。
問題は、元のオブジェクトが破棄されるとき (この例では最初のスコープの最後) に発生します。デストラクターは、新しいオブジェクトによってすでにコピーされている OpenGL オブジェクトを削除しようとします。この孤立した OpenGL オブジェクトは使用できなくなり、エラーが発生します。
この問題を解決するには、OpenGL オブジェクト ラッパーのカスタム コピーおよび移動セマンティクスを定義することが重要です。このアプローチにより、競合を引き起こすことなく、OpenGL オブジェクト参照がオブジェクト間で適切に転送されることが保証されます。
オブジェクトの移動には、そのリソースの所有権を別のオブジェクトに転送することが含まれます。コピーする代わりに、オブジェクトのリソースが新しいオブジェクトに割り当てられ、元のオブジェクトは有効ですが空の状態のままになります。このアプローチにより、潜在的な競合が防止され、OpenGL オブジェクトが有効なままになります。
以下の変更された BufferObject クラスでは、コピー コンストラクターとコピー代入演算子が削除され、移動セマンティクスが実装されます。
class BufferObject { private: GLuint buff_; public: BufferObject() { glGenBuffers(1, &buff_); } BufferObject(const BufferObject& other) = delete; BufferObject& operator=(const BufferObject& other) = delete; BufferObject(BufferObject&& other) : buff_(other.buff_) { other.buff_ = 0; } BufferObject& operator=(BufferObject&& other) { if (this != &other) { Release(); buff_ = other.buff_; other.buff_ = 0; } return *this; } ~BufferObject() { Release(); } void Release() { if (buff_) glDeleteBuffers(1, &buff_); } };
移動セマンティクスを実装することで、OpenGL オブジェクトの移動専用 RAII ラッパーを作成できます。このアプローチにより、C で OpenGL オブジェクトを安全かつ効率的に処理できるようになります。
以上がC RAII クラスの OpenGL オブジェクトがコピー後に動作しなくなるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。