для создания оболочек RAII только для перемещения для объектов OpenGL.

я есть объект OpenGL в классе C ++. Поскольку я использую 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.

В чем дело?

Примечание: это попытка построить канонический ответ на эти вопросы.

Ответы на вопрос(1)

л конструктор копирования, вы получите сгенерированный компилятором конструктор копирования. Это просто копирует всех членов объекта.

Рассмотрим первый пример:

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 будет уничтожено после того, как оно будет скопировано в возвращаемое значение, что делает возвращаемый объект бесполезным.

Это все из-за нарушения так называемого «правила 3/5» в C ++. Вы создали деструктор без создания конструкторов копирования / перемещения / операторов присваивания. Плохо.

Чтобы решить эту проблему, ваши обертки объектов 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.
};

Естьразличные другие методы для создания оболочек RAII только для перемещения для объектов OpenGL.

Ваш ответ на вопрос