C++ C++;清除指向动态分配对象的指针向量会导致异常吗?
我有一个叫做C++ C++;清除指向动态分配对象的指针向量会导致异常吗?,c++,exception,pointers,vector,erase,C++,Exception,Pointers,Vector,Erase,我有一个叫做ClassA的类。这个ClassA包含指向类ClassB的动态分配对象的指针向量。ClassA的析构函数如下所示: ClassA::~ClassA() { for (vector<ClassB*>::iterator i = m_vActiveB.begin(), e = m_vActiveB.end(); i != e; ) { vector<ClassB*>::iterator tmp(i++); delete *t
ClassA
的类。这个ClassA
包含指向类ClassB
的动态分配对象的指针向量。ClassA
的析构函数如下所示:
ClassA::~ClassA() {
for (vector<ClassB*>::iterator i = m_vActiveB.begin(), e = m_vActiveB.end(); i != e; ) {
vector<ClassB*>::iterator tmp(i++);
delete *tmp;
m_vActiveB.erase(tmp);
}
}
ClassA::~ClassA()
{
for (auto e : m_vActiveB)
{
delete e;
}
}
ClassA::~ClassA(){
对于(向量::迭代器i=m_-vActiveB.begin(),e=m_-vActiveB.end();i!=e;){
向量::迭代器tmp(i++);
删除*tmp;
m_真空擦除(tmp);
}
}
在ClassC
中,我有一个ClassA
对象的向量。我当前的场景是这样的:如果我的ClassC
向量中没有任何ClassA
对象,那么一切都可以正常工作。但是如果我在那里有对象,然后在ClassC
中对我的向量调用.erase(),那么就会抛出一个异常。通过日志记录,我已经确定调用了ClassA
析构函数(应该是这样的,因为我的理解是.erase()
会销毁每个向量成员),但是当循环开始时会抛出异常
有人知道这可能是什么原因吗?谢谢 遵循并仅使用以下内容声明您的m_vActiveB
成员向量:
std::vector<ClassB> m_vActiveB;
std::vector m_vActiveB;
并让默认构造函数负责销毁。您也可以使用的向量,但是,就像您当前的解决方案一样,您不会利用数组中连续元素的自然效率
在我的系统中,类B的对象本身需要不断地从向量中添加、删除和更新,以保持状态模型 如果您的数据模型不能自然地基于元素是连续的且具有特定顺序这一事实,那么像
std::unordered_map
或std::unordered_set
这样的“未排序”关联容器可能是更好的解决方案,特别是如果你插入并移除不驻留在向量末尾的元素(而坐在中间)。
您可能还想看看和,它分别提供了快速插入和删除(不会使迭代器失效)以及两端的快速插入和删除(也不会使迭代器失效)
我记得改变向量内容会使所有指针失效。。对吗
如果调用yes,所有迭代器都将失效(包括结束迭代器的过去部分)。调用erase
也会使所有指向已删除对象的引用和指针无效(就像引用任何已销毁/解除分配的对象无效一样)。来自文档:
在擦除点或之后使迭代器和引用无效,包括end()迭代器
这意味着您的i
和e
迭代器都已无效。所以不要像现在这样在循环中使用erase
还应考虑:
std::shared_ptr
,而不是自己管理内存m_vActiveB.clear()
,但您甚至不需要这样做,因为:m_vActiveB
是一个成员。它会为你收拾好的,不用麻烦你自己清理了使用
vector::erase
时,将使向量中的任何其他迭代器无效
因此不能使用“传统”迭代器循环
最简单的方法是按照Rakibul Hasan的建议,删除所有指针,然后清除向量 在遍历向量时,您正在从向量中删除元素。这将使迭代器无效 应该是这样的:
ClassA::~ClassA() {
for (vector<ClassB*>::iterator i = m_vActiveB.begin(), e = m_vActiveB.end(); i != e; ) {
vector<ClassB*>::iterator tmp(i++);
delete *tmp;
m_vActiveB.erase(tmp);
}
}
ClassA::~ClassA()
{
for (auto e : m_vActiveB)
{
delete e;
}
}
您不必清除向量,它在析构函数完成后将被销毁。使用
std::vector::erase
会导致位于或超过擦除点的迭代器失效。因此,在第一次迭代之后,结束迭代器e
的过去时间不再有效
而是在每次迭代时直接与从std::vector::end
返回的迭代器进行比较。但是,在您的示例中,不需要删除任何内容,因为m_-vActiveB
是一个成员,并且在运行dtor后将自动销毁(delete
但是需要删除指向的数据)
当执行擦除操作时,迭代器i
也将失效,因为复制迭代器i
的tmp
,并且擦除它仍将导致从向量中擦除相同的元素(擦除迭代器的副本没有帮助)
更好的替代方法是使用C++11智能指针,例如可以自动处理分配和解除分配的std::unique_ptr
class ClassA {
std::vector<std::unique_ptr<ClassB>> m_vActiveB; // No need for explicit destructor.
/* ... */
};
A类{
std::vector m_vActiveB;//不需要显式析构函数。
/* ... */
};
或者,如果您没有使用多态性,或者有其他特定的原因使用指针,那么为什么要使用指针呢?只需使用一个
std:vector
为什么您首先持有指向动态分配对象的指针?我应该不这样做吗S@user1014679嗯,shared\u ptr
和unique\u ptr
是你的朋友,如果你使用其中一个,你甚至不需要迭代向量来销毁每个成员。@user1014679,不。请看。在这种情况下,清除向量没有意义,因为它即将被销毁。很公平,尽管对于其他正在搜索如何清除拥有其内容的指针向量的人而言;这对他们来说是很有用的,因为技术是将它们全部删除然后清除。好的,看起来最流行的是对象向量而不是指针