gpt4 book ai didi

c++ - C++ RAII 类中的 OpenGL 对象不再有效

转载 作者:太空宇宙 更新时间:2023-11-04 12:38:04 25 4
gpt4 key购买 nike

我在 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.

这是怎么回事?

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

最佳答案

所有这些操作都复制 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 复制到 vector 中的 BufferObject 中。因此,就在我们退出该范围之前,有两个 BufferObject 对象。

但是它们存储的是什么 OpenGL 缓冲区对象?好吧,他们存储相同的。毕竟,对于 C++,我们只是复制了一个整数。所以两个 C++ 对象存储相同的整数值。

当我们退出该作用域时,some_buffer 将被销毁。因此,它将对该 OpenGL 对象调用 glDeleteBuffers。但是 vector 中的对象仍然有它自己的那个 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.
};

various other techniques用于为 OpenGL 对象制作仅移动的 RAII 包装器。

关于c++ - C++ RAII 类中的 OpenGL 对象不再有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55503026/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com