我有一个vector
,其中有pointer
个课程:
vector<Entity*> editorElements;
vector<Entity*> entities;
vector<DirectionalLight*> dirLights;
vector<PointLight*> pointLights;
vector<SpotLight*> spotLights;
此代码在我的课程Scene
中。 Scene
的ctor和析构函数如下:
Scene()
{
editorElements = vector<Entity*>();
entities = vector<Entity*>();
dirLights = vector<DirectionalLight*>();
pointLights = vector<PointLight*>();
spotLights = vector<SpotLight*>();
}
~Scene()
{
delete[] &entities; // ERROR HERE
delete[] &dirLights;
delete[] &pointLights;
delete[] &spotLights;
delete[] &editorElements;
}
在析构函数中,我标记了一行ERROR HERE
。我先输入哪个向量都没有关系,但我总是会得到错误。
奇怪的是,直到最近(没有触及Scene
类或使用Scene
实例的任何其他类中的任何东西),它的工作状况都很好,突然间它引发了一个异常:
vector
是否为空或是否具有元素都没有关系,它给出的错误都相同。
我需要协助才能解决此问题。
答案 0 :(得分:2)
向量不是更新的指针,更不用说更新的数组了。因此,您不应该删除它们。 如果 ,您需要调用向量中存储的指针的delete,则应遍历向量,删除每个元素。但是最好改为存储智能指针(例如router.post('/checkAuth', function (req, res) {
console.log(req.body.key)
if (!req.body.key) {
console.log('enter')
}
jwt.verify(req.body.key, 'MatchaSecretKey', function(err, decoded) {
if (err) {
res.send({'result': false})
}
else {
res.send({'result': true})
}
})
});
。那就是如果您需要存储所有指向动态分配对象的指针。
请注意,如果最终删除了析构函数中的元素,则还需要注意rule of three/five。
答案 1 :(得分:2)
delete expression delete [] x
的描述如下:
销毁由new []-表达式创建的数组
因此,如果delete[] &entities
是由&entities
表达式创建的数组,那么new[]
仅 才有意义。对吧?
但是entities
是std::vector<Entity*>
,而不是Entity[]
。您没有使用new[]
创建它,因此您绝对不能使用delete[]
删除它。
std::vector
不是数组的语法糖,它是模板类,而std::vector<Entity*> entities
不是数组,它是具有构造函数和析构函数的对象。那也告诉我们这句话
entities = vector<Entity*>();
没有任何用处-entities
是一个对象,因此它已经是默认构造的。您只是默认构造一个相同类型的匿名临时文件,然后对其进行分配。
最后,在这里将原始指针存储在向量中是可以的,因为向量不负责对象的生存期。在大多数情况下,最好让向量拥有对象,这样您就不必担心直接通过
手动删除它们vector<Entity>
或间接
vector<unique_ptr<Entity>>
NB。一个很好的指导原则是:根本不要在用户代码中使用new
,new[]
,delete
或delete[]
。
使用类对象来管理您的存储,因为编译器将为您调用其构造函数和析构函数。
如果您需要一个自定义类,请编写一个仅用于 来管理内存的类,以免与程序逻辑脱钩。否则,如果您确实需要所有权模型等,请使用标准的库工具,例如std::vector
,std::array
,std::unique_ptr
,std::shared_ptr
。
答案 2 :(得分:1)
突然间它引发了异常
这是因为尝试删除不应该删除的内容。 The delete[]
syntax用于删除动态分配的 array 。但是,您为它提供了一个指向std::vector
实例的指针。因此,编译器将此地址当作删除对象,就好像它是一个数组一样,其中包括找出其大小,然后删除整个段。但是没有合适的数字,因为它不是数组,所以在运行时,您最终试图在没有访问权限的地方删除某些内容,因此断言失败,因为这是访问违反,又名段错误。
此外,vector
是一个管理自己的内存的类。如果要释放保存在此容器中的实体(即,动态分配的各个元素本身),则应遍历它们并删除每个元素。方便地,例如,使用auto
和range-based for loop像这样:
for (auto ptr : entities)
delete ptr;
但是,在大多数情况下,您最好节省自己的内存管理开销,并选择std::unique_ptr
而不是原始指针:
#include <memory>
...
std::vector<std::unique_ptr<Entity>> entities;
通过这种方式,您不必担心释放任何内存,因为std:: unique_ptr
一旦被销毁就会被释放,这是vector
销毁的一部分。
此外,这是不必要的,可能不是您打算要做的:
entities = vector<Entity*>();
由于vector
对象本身已经在此行之前定义了(因此存在),并且它所做的就是创建一个相同的新对象并将其分配给entities
。