首页 >后端开发 >C++ >如何避免在 C RAII 中复制和移动 OpenGL 对象包装器时出现问题?

如何避免在 C RAII 中复制和移动 OpenGL 对象包装器时出现问题?

Susan Sarandon
Susan Sarandon原创
2024-12-02 15:44:11623浏览

How to Avoid Issues with OpenGL Object Wrapper Copying and Moving in C   RAII?

C RAII 中的 OpenGL 对象包装器:对象所有权故障排除

在 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 对象包装器必须是仅移动类型。这可以通过以下方式实现:

  1. 删除复制构造函数和复制赋值运算符:
BufferObject(const BufferObject &) = delete;
BufferObject &operator=(const BufferObject &) = delete;
  1. 提供移动构造函数和移动赋值运算符:
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中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn