C+中的OpenGL对象+;RAII类不再工作 我在C++类中有一个OpenGL对象。因为我在使用RAII,我想让析构函数删除它。所以我的课看起来像: class BufferObject { private: GLuint buff_; public: BufferObject() { glGenBuffers(1, &buff_); } ~BufferObject() { glDeleteBuffers(1, &buff_); } //Other members. };

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

这似乎有效。但每当我执行以下操作时,我在使用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.
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.
};