【发布时间】:2020-08-07 07:31:06
【问题描述】:
我在 C++ 类中有一个 OpenGL 对象。因为我正在使用 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.
发生了什么事?
注意:这是对这些问题建立规范答案的尝试。
【问题讨论】:
-
@bartop: "构造函数应该是无代码的" 这与现代(甚至更早)C++ 编程的几乎所有想法背道而驰。在构造函数中分配资源是智能指针的基石,它甚至是 C++ 核心指南的一部分。
-
对不起,什么?没有一个智能指针在其构造函数中分配资源。为此,它们具有特殊的工厂功能。将代码放在构造函数中通常是个坏主意,因为错误很难处理,并且对象可能会处于不可预测的状态
-
@bartop: "没有一个智能指针在其构造函数中分配资源。" 你认为
shared_ptr的共享状态来自哪里?该共享状态必须动态分配,以便它可以被其他shared_ptr实例共享,并且它需要能够比资源寿命更长,以便weak_ptr工作。shared_ptr在其构造函数中为共享状态分配内存。这实际上忽略了标准库中的每个容器,如果您将数据传递给它们,所有这些容器都会在它们的构造函数中分配。或在其构造函数中打开文件的文件流。等等。 -
@bartop:因此,尽管您个人可能认为“构造函数应该是无代码的”,但实际上 C++ 并非如此。从 Boost 到 Qt 再到 Poco,几乎每个 C++ 库都具有执行实际工作的对象构造函数。这是RAII的基础。 “错误难以处理,对象可能处于不可预知的状态”这就是例外。