我在为Model
课程编写/使用析构函数时遇到了问题。对于OpenGL分配,我必须编写一个数据结构,其中包含有关模型的所有信息,请参阅下面的Model.h
实现。这个类包含指向各种结构的指针,我已经学会了在堆上分配内存后正确清理。
目前,我的应用程序工作正常,同时让我的析构函数注释掉,这确实给了我内存泄漏但我很确定我的讲师会给我一个重要的因此而降低等级。
但是,在定义(取消注释)我的析构函数时,我会遇到问题。在运行一个名为InitModels
的方法(参见下面的实现)之后,我的析构函数被调用,它会抛出一个应用程序中断异常:
我在这里缺少什么?我听过并读过一些关于三个规则的内容,这可能与我的问题有关,但我被困在哪里开始在我的案例中应用这条规则。
这是我的InitModels
方法:
void InitModels()
{
/*
Teapot model
*/
Model teapot("Teapot");
teapot.material = new Material(glm::vec3(0.0, 0.0, 0.0),
glm::vec3(0.0, 0.0, 0.0),
glm::vec3(1.0), 128);
teapot.mesh = new Mesh("Objects/teapot.obj");
teapot.modelMatrix = new ModelMatrix(glm::mat4());
teapot.texture = new Texture("Textures/Yellobrk.bmp", true, loadBMP("Textures/Yellobrk.bmp"));
teapot.transformations = new Transformations(true, 0.01f, glm::vec3(0.0f, 1.0f, 0.0f));
models.push_back(teapot);
}
这是我的Model.h
:
#include <iostream>
#include <vector>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "glsl.h"
#include "objloader.hpp"
#pragma once
struct Material
{
glm::vec3 ambientColor;
glm::vec3 diffuseColor;
glm::vec3 specular;
float power;
/*
Initializer list constructor
*/
Material(){ }
Material(glm::vec3 ambient, glm::vec3 diffuse, glm::vec3 spec, float pwr) :
ambientColor(ambient), diffuseColor(diffuse), specular(spec), power(pwr) { }
};
struct Mesh
{
char* fileLocation; // location of object file
vector<glm::vec3> vertices;
vector<glm::vec3> normals;
vector<glm::vec2> uvs;
/*
Initializer list constructor
*/
Mesh(char* fileLoc) : fileLocation(fileLoc) { }
Mesh(char* fileLoc, vector<glm::vec3> vert, vector<glm::vec3> normals, vector<glm::vec2> uvs) :
fileLocation(fileLoc), vertices(vert), normals(normals), uvs(uvs) { }
~Mesh() { }
};
struct ModelMatrix
{
glm::mat4 model;
glm::mat4 mv;
/*
Initializer list constructor
*/
ModelMatrix() { }
ModelMatrix(glm::mat4 model) : model(model) { }
ModelMatrix(glm::mat4 model, glm::mat4 mv) : model(model), mv(mv) { }
};
struct Texture
{
char* fileLocation; // location of texture file
bool applyTexture;
GLuint textureID;
/*
Initializer list constructor
*/
Texture() { }
/*Texture(char* fileLocation, bool applyTexture) :
fileLocation(fileLocation), applyTexture(applyTexture)
{
textureID = loadBMP(fileLocation);
}*/
Texture(char* fileLocation, bool applyTexture, GLuint textureID) :
fileLocation(fileLocation), applyTexture(applyTexture), textureID(textureID) { }
~Texture() { }
};
struct Transformations
{
bool rotationEnabled;
float angle;
glm::vec3 axis;
Transformations() { }
Transformations(bool rotEnabled, float angle, glm::vec3 axis)
: rotationEnabled(rotEnabled), angle(angle), axis(axis) { }
~Transformations() { }
};
class Model {
public:
Model(string modelName)
{
name = modelName;
}
~Model();
string name;
GLuint vao;
Material * material;
Texture* texture;
Mesh* mesh;
ModelMatrix* modelMatrix;
Transformations* transformations;
};
答案 0 :(得分:1)
&#34;我听过并读过一些关于三个规则的内容,这可能与我的问题有关&#34; 你是对的。 https://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)
在void InitModels()
中,您在堆栈上创建Model
,然后将副本推送到向量models.push_back(teapot);
,
您没有定义复制构造函数,因此编译器会创建默认构造函数。它只是做一个简单的指针副本。
一旦代码超出范围,就会调用此项的析构函数。并且指针变为无效,因此向量中的项目现在具有无效指针。
一旦调用了向量析构函数,它就会调用Model
的析构函数,并对已删除的指针进行删除。
您可以使用unique_ptr修复此问题并定义复制构造函数。