我正在使用为Visual Studio 2008编译的Qt5.1。
我正在尝试渲染具有多个纹理的对象。在我的原始代码中,我使用网格类来管理加载3D对象,这基于本教程:
http://ogldev.atspace.co.uk/www/tutorial22/tutorial22.html
网格类包含一个包含纹理的矢量。纹理从文件加载图像数据,并跟踪渲染自身所需的所有OpenGL状态管理。
当我尝试使用Qt向我的网格类向量容器中添加多个纹理时,我收到“调试断言失败:_BLOCK_TYPE_US_VALID(pHead-> nBlockUse)”错误。在向向量添加纹理时调用析构函数时会发生此错误,类似于此线程中描述的内容:
Destructor called on object when adding it to std::list
我是Qt的新手,我想知道在这种情况下处理纹理的最佳方法是什么。教程代码使用GLEW而不是Qt,我不得不从QOpenGLFunctions继承来管理OpenGL状态以渲染纹理(我的网格类也继承自QOpenGLFunctions)。看起来默认的复制构造函数正在执行纹理对象的浅表副本,这会删除由Qt管理的内存。但是,当我切换到使用列表容器进行纹理时,我没有得到断言错误。
以下是我的代码的简化,说明了我的问题:
#include <QOpenGLFunctions_3_3_Core>
#include <list>
#include <vector>
class Texture : protected QOpenGLFunctions_3_3_Core
{
public:
Texture()
{
}
~Texture()
{
std::cout << "destructor" << std::endl;
}
};
std::vector<Texture> textureList; //this causes the assertion failure
//std::list<Texture> textureList; //this works
void tester()
{
for (int i = 0; i < 3; i++)
{
Texture Texture;
textureList.push_back(Texture);
}
}
int main()
{
tester();
//Qt application code
}
答案 0 :(得分:0)
此问题来自vector
和list
之间内部实施的差异。
首先,list
是双向链接列表,因此list
可以在没有原始元素副本的情况下增长。但vector
是动态分配的数组。如果vector
的容量已满,vector
将分配具有更大大小(Array doubling)的新数组,并将旧数组中的元素复制到新数组。下面的代码段显示了断言发生的原因。 (也许)
#include <iostream>
#include <list>
#include <vector>
class Texture
{
public:
Texture()
{
std::cout << "constructor" << std::endl;
}
Texture(const Texture &t)
{
std::cout << "copy constructor" << std::endl;
}
~Texture()
{
std::cout << "destructor" << std::endl;
}
};
std::vector<Texture> textureList;
//std::list<Texture> textureList;
void tester()
{
for (int i = 0; i < 3; i++)
{
//textureList.reserve(4);
std::cout << "Loop\n";
Texture texture;
textureList.push_back(texture);
std::cout << "Capacity: " << textureList.capacity() << "\n";
}
std::cout << "End\n";
}
int main()
{
std::cout << "main\n";
tester();
std::cout << "main end\n";
}
<强>结果强>
main
Loop
constructor
copy constructor
Capacity: 1
destructor
Loop
constructor
copy constructor
copy constructor
destructor
Capacity: 2
destructor
Loop
constructor
copy constructor
copy constructor
copy constructor
destructor
destructor
Capacity: 4
destructor
End
main end
destructor
destructor
destructor
每当矢量增长时,纹理实例都会被销毁。
如果您阻止此问题,请使用vector::reserve
(请查看以上代码:textureList.reserve(4)
)。但我认为这个代码会出现另一个问题,所以我建议使用纹理指针而不是纹理实例来处理。