C ++ RAII类中的OpenGL对象不再起作用

我在C ++类中有一个OpenGL对象。由于我正在使用RAII,因此我希望析构函数将其删除。所以我的课看起来像这样:


class BufferObject

{

private:

  GLuint buff_;


public:

  BufferObject()

  {

    glGenBuffers(1, &buff_);

  }


  ~BufferObject()

  {

    glDeleteBuffers(1, &buff_);

  }


//Other members.

};

这似乎可行。但是无论何时执行以下任何操作,使用它时我都会开始遇到各种OpenGL错误:


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.

这是怎么回事?


注意:这是为这些问题建立规范答案的尝试。


凤凰求蛊
浏览 452回答 3
3回答

侃侃尔雅

所有这些操作都复制C ++对象。由于您的类未定义副本构造函数,因此您将获得编译器生成的副本构造函数。这只是复制对象的所有成员。考虑第一个示例:vector<BufferObject> bufVec;{&nbsp; BufferObject some_buffer;&nbsp; //Initialize some_buffer;&nbsp; bufVec.push_back(some_buffer);}bufVec.back(); //buffer doesn't work.当你调用push_back,它复制some_buffer到一个BufferObject在vector。因此,在退出该范围之前,有两个BufferObject对象。但是它们存储什么OpenGL缓冲区对象?好吧,它们存储相同的一个。毕竟,对于C ++,我们只是复制了一个整数。因此,两个C ++对象都存储相同的整数值。当我们退出该范围时,some_buffer将被销毁。因此,它将调用glDeleteBuffers此OpenGL对象。但是向量中的对象仍将具有其自己的OpenGL对象名副本。其中已被摧毁。因此,您不能再使用它;因此错误。InitBuffer函数也会发生同样的事情。buff复制到返回值后将被销毁,这使返回的对象变得毫无价值。这都是由于违反了C ++中所谓的“ 3/5规则”。您创建的析构函数没有创建复制/移动构造函数/赋值运算符。那很糟。为了解决这个问题,您的OpenGL对象包装器应为仅移动类型。您应该删除复制构造函数和复制分配运算符,并提供将从其移动的对象设置为对象0的移动等效项:class BufferObject{private:&nbsp; GLuint buff_;public:&nbsp; BufferObject()&nbsp; {&nbsp; &nbsp; glGenBuffers(1, &buff_);&nbsp; }&nbsp; BufferObject(const BufferObject &) = delete;&nbsp; BufferObject &operator=(const BufferObject &) = delete;&nbsp; BufferObject(BufferObject &&other) : buff_(other.buff_)&nbsp; {&nbsp; &nbsp; other.buff_ = 0;&nbsp; }&nbsp; BufferObject &operator=(BufferObject &&other)&nbsp; {&nbsp; &nbsp; //ALWAYS check for self-assignment&nbsp; &nbsp; if(this != &other)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; Release();&nbsp; &nbsp; &nbsp; buff_ = other.buff_;&nbsp; &nbsp; &nbsp; other.buff_ = 0;&nbsp; &nbsp; }&nbsp; &nbsp; return *this;&nbsp; }&nbsp; ~BufferObject() {Release();}&nbsp; void Release();&nbsp; {&nbsp; &nbsp; if(buff_)&nbsp; &nbsp; &nbsp; glDeleteBuffers(1, &buff_);&nbsp; }//Other members.};还有许多其他技术可为OpenGL对象制作仅移动RAII包装。
打开App,查看更多内容
随时随地看视频慕课网APP