C+中的OpenGL对象+;RAII类不再工作 我在C++类中有一个OpenGL对象。因为我在使用RAII,我想让析构函数删除它。所以我的课看起来像: class BufferObject { private: GLuint buff_; public: BufferObject() { glGenBuffers(1, &buff_); } ~BufferObject() { glDeleteBuffers(1, &buff_); } //Other members. };
这似乎有效。但每当我执行以下操作时,我在使用OpenGL时就会出现各种错误:C+中的OpenGL对象+;RAII类不再工作 我在C++类中有一个OpenGL对象。因为我在使用RAII,我想让析构函数删除它。所以我的课看起来像: class BufferObject { private: GLuint buff_; public: BufferObject() { glGenBuffers(1, &buff_); } ~BufferObject() { glDeleteBuffers(1, &buff_); } //Other members. };,c++,c++11,opengl,C++,C++11,Opengl,这似乎有效。但每当我执行以下操作时,我在使用OpenGL时就会出现各种错误: vector<BufferObject> bufVec; { BufferObject some_buffer; //Initialize some_buffer; bufVec.push_back(some_buffer); } bufVec.back(); //buffer doesn't work. BufferObject InitBuffer() { BufferObject b
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.
vectorbufvec;
{
BufferObject一些_缓冲区;
//初始化一些缓冲区;
bufVec.向后推(一些缓冲);
}
bufVec.back()//缓冲区不工作。
BufferObject InitBuffer()
{
缓冲对象buff;
//用buff做东西`
返回buff;
}
自动buff=InitBuffer()//返回的缓冲区不工作。
发生什么事了
注:这是一个试图对这些问题建立一个规范的答案。 < P>所有这些操作都复制C++对象。因为您的类没有定义复制构造函数,所以您得到了编译器生成的复制构造函数。这只是复制对象的所有成员 考虑第一个例子:
vector<BufferObject> bufVec;
{
BufferObject some_buffer;
//Initialize some_buffer;
bufVec.push_back(some_buffer);
}
bufVec.back(); //buffer doesn't work.
对于OpenGL对象,有一些只用于移动的RAII包装器。所有操作都复制缓冲区对象。但是,由于您的类没有复制构造函数,所以它只是一个浅复制。当析构函数在不进行进一步检查的情况下删除缓冲区时,缓冲区将与原始对象一起删除。Nicol Bolas建议定义一个移动构造函数、删除复制构造函数和复制赋值操作符,我将描述一种不同的方法,以便在复制后两个缓冲区都可用 您可以使用
std::map
数组轻松跟踪有多少对象使用单个对象。考虑下面的示例代码,这是代码的扩展:
#包括
标准::地图参考计数;
类缓冲对象
{
私人:
胶合浅黄色;
公众:
缓冲对象()
{
glGenBuffers(1,&buff_);
reference\u count[buff\u]=1;//将reference count设置为其初始值1
}
~BufferObject()
{
reference_count[buff_]-->//减少引用计数
if(reference_count[buff_]@bartop:“构造函数应该是无代码的”,这几乎违背了现代(甚至更古老)的所有理念C++编程:在构造函数中分配资源是智能指针的基石,甚至是C++核心指南的一部分。请问,什么?智能指针中没有一个在其构造函数中分配资源。为此,它们有特殊的工厂函数。句柄和对象可能处于不可预测状态state@bartop:“没有智能指针在其构造函数中分配资源。”您认为shared_ptr
的共享状态从何而来?必须动态分配该共享状态,以便其他shared_ptr
实例可以共享该共享状态,并且它需要能够比资源寿命长,以便weak_ptr
工作。shared_ptr
为i中的共享状态分配内存ts构造函数。这实际上忽略了标准库中的每个容器,如果您将数据传递给它们存储,所有容器都会在它们的构造函数中分配。或者在它们的构造函数中打开文件的文件流。等等@bartop:所以,尽管您个人认为“构造函数应该是无代码的”实际上,不是每个C++ C++都是如何运行的,而是每个C++库都有实际的工作对象构造。它是RAII的基础。“错误很难处理,对象可能会处于不可预知的状态”,这就是例外。与我做了类似的事情,但是添加了一个布尔“HasyRealthor”。携带而不是检查buff_uuu是否为0。是否可以安全地假设没有任何内容将被分配为0作为id?@Barnack:Zero对于缓冲区对象或大多数OpenGL对象都不是有效的名称。即使对于有效的对象,它也不表示可以删除的对象(成功;使用0调用glDelete*
将不会导致任何事情发生)。@Nicolas感谢您提出这个问题并自行回答。不过我有一个问题。您正在调用Release()
在move assignment操作符中,但是该方法不应该简单地移动id而不在该点释放缓冲区,因为它正在转移所有权吗?@JohnH:move assignment中的这个
对象就是被分配给的对象。该对象可能仍然拥有缓冲区的所有权。为了声明新对象的所有权,它必须“释放”它已经拥有的任何缓冲区的所有权。一个常见的替代方法是交换这两个对象,将以前拥有的缓冲区留在另一个对象中,而另一个对象本身最终将被销毁。@Nicolas啊,我明白你的意思了!我误读了它。谢谢你的澄清。
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.
};