C 中OpenGL 物件的RAII :了解隱藏的問題
在C 物件導向程式設計中,資源取得就是初始化(RAII)是用於有效管理資源的技術。在 C 類別中使用 OpenGL 物件時,通常需要使用 RAII 來確保類別銷毀時正確釋放 OpenGL 物件。
考慮以下程式碼片段:
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中文網其他相關文章!