在C 中,RAII(資源取得即初始化)用於確保資源在使用時自動釋放不再需要。此模式通常應用於 OpenGL 物件。然而,在為 OpenGL 物件實作 RAII 時有時會出現問題,導致它們停止運作。
嘗試複製或移動 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中文網其他相關文章!