在 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_;
};

請注意,物件是可構造的,但不能移動 - 可分配。這樣做的想法是防止重新繫結範圍的緩衝區繫結。一旦設定,唯一可以解除它的東西就是被移除。