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中文网其他相关文章!