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包裝。
- 3 回答
- 0 關注
- 485 瀏覽
添加回答
舉報