亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

C ++ RAII類中的OpenGL對象不再起作用

C ++ RAII類中的OpenGL對象不再起作用

C++
鳳凰求蠱 2019-11-20 09:39:34
我在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.這是怎么回事?注意:這是為這些問題建立規范答案的嘗試。
查看完整描述

3 回答

?
侃侃爾雅

TA貢獻1801條經驗 獲得超16個贊

所有這些操作都復制C ++對象。由于您的類未定義副本構造函數,因此您將獲得編譯器生成的副本構造函數。這只是復制對象的所有成員。


考慮第一個示例:


vector<BufferObject> bufVec;

{

  BufferObject some_buffer;

  //Initialize some_buffer;

  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:

  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對象制作僅移動RAII包裝。


查看完整回答
反對 回復 2019-11-20
  • 3 回答
  • 0 關注
  • 485 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號