问题描述
当我尝试为OpenGL缓冲区对象编写RAII包装器类时,出现了这个问题。 OpenGL创建缓冲区对象的方式是通过调用void glGenBuffers(GLsizei n,GLuint* buffers)
来实现,该调用“返回n
中的buffers
个缓冲区对象名称。”另外,请注意,对象名称0
对于OpenGL是特殊的,它是默认值"like a NULL pointer."
buffer_object
我想要两种不同的初始化行为:
- 如果我创建数组
class buffer_object { public: // constructors,destructor private: unsigned int const name; };
,我希望std::array<buffer_object,N> buffer_obj_array {};
数组元素的buffer_object
初始化为0。其他容器也是如此。 - 如果我创建一个局部变量,请不要初始化为0,而是通过调用
name
来给它起一个名字。
问题是我不完全了解列表初始化,值初始化和默认初始化。
关于glGenBuffers(1,&name)
的默认构造函数,cppreference.com说它使用聚合初始化,这是列表初始化的一种,该值初始化数组中初始化列表中未提供的元素。关于值初始化,请访问cppreference.com says,
那么,这是否意味着无法执行以下操作?
std::array
解决方法
C ++对象初始化不是也不能基于创建该对象的所在位置(除了琐碎类型的默认初始化对象外,该初始化对象在用于全局变量时为零初始化,但不适用于自动广告。
如果给一个类型一个非平凡的默认构造函数,则说明该类型的对象需要必须执行一些真实的代码,才能被认为是该类型的有效对象,这是一个强有力的声明。因此,C ++会假设您认真对待此声明,并确保在创建该类型的对象的所有情况下都执行所述“真实代码”。
如果为buffer_object
提供了一个默认的构造函数,该构造函数生成一个缓冲区对象,则表示该类型的对象应始终拥有一个有效的OpenGL缓冲区对象(可能从其移出时除外)。如果为buffer_object
提供了一个默认构造函数,该构造函数将内部缓冲区对象句柄清零,则表示没有OpenGL缓冲区对象句柄是buffer_object
处于正常,有效的状态。
这两个陈述没有半途而废。默认值为空或不是。
现在,您可以具有备用构造函数了。默认构造函数可以使句柄为零,而另一个构造函数采用简单的标记类型,明确声明它将生成一个句柄。或更妙的是,工厂函数如何使buffer_object
生成了句柄:
buffer_object gen_buffer()
{
GLuint handle = 0;
glGenBuffers(1,&handle);
return buffer_object(handle);
};
auto obj = gen_buffer(); //Clearly states what is going on.
现在毫无疑问obj
中有什么:它具有一个生成的缓冲区对象句柄。因为这就是代码所说的话。