C の OpenGL オブジェクトを使用した RAII : 隠れた問題を理解する
C オブジェクト指向プログラミングでは、リソースの取得は初期化 (RAII) です。リソースを効率的に管理するために使用される手法。 C クラス内で OpenGL オブジェクトを使用する場合、クラスが破棄されたときに OpenGL オブジェクトが正しく解放されるように RAII を使用するのが一般的です。
次のコード スニペットを検討してください。
class BufferObject { private: GLuint buff_; public: BufferObject() { glGenBuffers(1, &buff_); } ~BufferObject() { glDeleteBuffers(1, &buff_); } };
このクラスは OpenGL オブジェクトに対して RAII を正しく実装しているようです。ただし、次のコードに示すように、クラスをコピーまたは移動すると問題が発生します。
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.
これらのシナリオでは、OpenGL オブジェクトが使用できなくなり、エラーが発生します。
理由この動作は、コンパイラによって生成されるデフォルトのコピー コンストラクターと代入演算子にあります。これらの操作はオブジェクトのメンバーをコピーするだけであり、その結果、複数の C オブジェクトが同じ基礎となる OpenGL オブジェクトを参照することになります。元の C オブジェクトが破棄されると、OpenGL オブジェクトが解放され、他のオブジェクトが破棄されたリソースを参照するようになります。
この問題を解決するには、BufferObject クラスを移動専用型にする必要があります。これは、コピー コンストラクターと代入演算子を削除し、OpenGL オブジェクトの所有権を新しいオブジェクトに譲渡する同等の移動を提供することを意味します。
class BufferObject { private: GLuint buff_; public: BufferObject() { glGenBuffers(1, &buff_); } BufferObject(const BufferObject &) = delete; BufferObject &operator=(const BufferObject &) = delete; BufferObject(BufferObject &&other) : buff_(other.buff_) { other.buff_ = 0; } BufferObject &operator=(BufferObject &&other) { //ALWAYS check for self-assignment if(this != &other) { Release(); buff_ = other.buff_; other.buff_ = 0; } return *this; } ~BufferObject() {Release();} void Release(); { if(buff_) glDeleteBuffers(1, &buff_); } //Other members. };
これらの変更により、クラスは OpenGL オブジェクトが正しく管理され、クラスをコピーまたは移動する場合でも解放されます。
以上がC の OpenGL オブジェクトを使用した RAII は、オブジェクトのコピーまたは移動時に予期しない動作を引き起こす可能性がありますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。