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中文網其他相關文章!