C では、RAII (リソース取得は初期化) を使用して、リソースがリソースの取得時に自動的に解放されるようにします。もう必要ありません。このパターンは一般に OpenGL オブジェクトに適用されます。ただし、OpenGL オブジェクトに RAII を実装するときに問題が発生し、動作が停止することがあります。
そのような問題の 1 つは、OpenGL オブジェクト ラッパーをコピーまたは移動しようとすると発生します。デフォルトでは、C はオブジェクトのメンバーを単純にコピーするコピー コンストラクターを生成します。 OpenGL オブジェクト ラッパーの場合、両方のコピーが同じ OpenGL オブジェクトを参照します。
次のコードを考えてみましょう。
// An OpenGL object wrapper with RAII class BufferObject { public: BufferObject() { glGenBuffers(1, &buff_); } ~BufferObject() { glDeleteBuffers(1, &buff_); } private: GLuint buff_; }; // Vector of buffer objects vector<BufferObject> bufVec; { BufferObject some_buffer; // Create buffer object // Initialize some_buffer // Copy some_buffer into the vector bufVec.push_back(some_buffer); } // Error: bufVec.back() will reference a deleted object // Function returning a buffer object BufferObject InitBuffer() { BufferObject buff; // Create buffer object // Do stuff with buff // Return a copy of buff return buff; } // Error: The returned buffer will reference a deleted object auto buff = InitBuffer();
この例では、some_buffer のコピーが bufVec に追加され、 InitBuffer() から返されたバッファは両方とも同じ OpenGL オブジェクトを参照します。 some_buffer がスコープの終了時に破棄されると、OpenGL オブジェクトが削除されます。これにより、buffVec.back() と返されたバッファが使用できなくなり、エラーが発生します。
これを解決するには、OpenGL オブジェクト ラッパーは移動専用タイプである必要があります。これは、
BufferObject(const BufferObject &) = delete; BufferObject &operator=(const BufferObject &) = 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; }
これらの変更により、コピーが発生しないことが保証され、 OpenGL オブジェクトはコピーされずに移動されます。
以上がC RAII での OpenGL オブジェクト ラッパーのコピーと移動の問題を回避するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。