在 C11 及更高版本
C++ 11 提供了增強 RAII 封裝的 OpenGL 物件功能的工具。如果沒有像移動語義這樣的 C++ 11 特性,如果你想傳遞它們,就必須動態分配這些物件,因為它們無法被複制。移動支援允許它們像普通值一樣來回傳遞,但不能通過複製:
class BufferObject
{
public:
BufferObject(GLenum target, GLsizeiptr size, const void *data, GLenum usage)
{
glGenBuffers(1, &object_);
glBindBuffer(target, object_);
glBufferData(target, size, data, usage);
glBindBuffer(target, 0);
}
//Cannot be copied.
BufferObject(const BufferObject &) = delete;
BufferObject &operator=(const BufferObject &) = delete;
//Can be moved
BufferObject(BufferObject &&other) noexcept : object_(other.Release())
{}
//Self-assignment is OK with this implementation.
BufferObject &operator=(BufferObject &&other) noexcept
{
Reset(other.Release());
}
//Destroys the old buffer and claims ownership of a new buffer object.
//It's OK to call glDeleteBuffers on buffer object 0.
GLuint Reset(GLuint object = 0)
{
glDeleteBuffers(1, &object_);
object_ = object;
}
//Relinquishes ownership of the object without destroying it
GLuint Release()
{
GLuint ret = object_;
object_ = 0;
return ret;
}
~BufferObject()
{
Reset();
}
//Accessors and manipulators
void Bind(GLenum target) const {glBindBuffer(target, object_);}
GLuint GetObject() const {return object_;}
private:
GLuint object_;
};
這樣的型別可以通過函式返回:
BufferObject CreateStaticBuffer(GLsizeiptr byteSize) {return BufferObject(GL_ARRAY_BUFFER, byteSize, nullptr, GL_STATIC_DRAW);}
這允許你將它們儲存在你自己的(隱式移動)型別中:
struct Mesh
{
public:
private:
//Default member initializer.
BufferObject buff_ = CreateStaticBuffer(someSize);
};
範圍繫結器類也可以具有移動語義,從而允許從函式返回繫結器並將其儲存在 C++標準庫容器中:
class BindBuffer
{
public:
BindBuffer(GLenum target, const BufferObject &buff) : target_(target)
{
buff.Bind(target_);
}
//Non-copyable.
BindBuffer(const BindBuffer &) = delete;
BindBuffer &operator=(const BindBuffer &) = delete;
//Move-constructible.
BindBuffer(BindBuffer &&other) noexcept : target_(other.target_)
{
other.target_ = 0;
}
//Not move-assignable.
BindBuffer &operator=(BindBuffer &&) = delete;
~BindBuffer()
{
//Only unbind if not moved from.
if(target_)
glBindBuffer(target_, 0);
}
private:
GLenum target_;
};
請注意,物件是可構造的,但不能移動 - 可分配。這樣做的想法是防止重新繫結範圍的緩衝區繫結。一旦設定,唯一可以解除它的東西就是被移除。