c++不需要删除迭代器

C++ does the iterator need to be deleted?

本文关键字:迭代器 删除 不需要 c++      更新时间:2023-10-16

我有一个关于内存释放的问题

我正在我的一个程序中迭代一个向量。像这样:

// init vector
vector<int>* v = new vector<int>();
// iterate
for (vector<Column>::iterator it = v->begin(); it != v->end(); ++it) {
    // do something with it
}
// delete vector
delete v;

但是我觉得不确定,如果我应该写:

// init vector
vector<int>* v = new vector<int>();
// iterate
vector<Column>::iterator it = v->begin()
for (; it != v->end(); ++it) {
    // do something with it
}
delete it;
// delete vector
delete v;

还是因为释放了迭代器,所以不需要释放迭代器?

只能对迭代器保存的对象调用delete,而不能对迭代器本身调用delete;以您的代码为例(稍作修改):

std::vector<int*> *v = new std::vector<int*>();
for (int i = 0; i < 10; ++i) {
    v->push_back(new int(i));
}
std::vector<int*>::iterator it = v->begin();
for (; it != v->end(); ++it) {
    // do something with it
    delete *it; // <- notice the deference to delete the underlying int 
    //delete it; // causes compiler error (expected pointer)
}
// delete vector
delete v;

在迭代器类型上调用delete会生成编译器错误(取决于编译器/实现等)

根据我的经验,你永远不会删除迭代器。最重要的是,迭代器只需要很少量的内存

迭代器不拥有(观察)。它们是为容器"产生"的,但实际上并不是保存内存的对象。因此,您不仅不需要,而且一定不能删除它们。

另一方面,当容器为其持有的对象分配内存时,可以并且应该通过迭代器释放

。一个示例

vector<int*> v(10);
std::generate(v.begin(), v.end(), []() { return new int; });

释放v中所有对象的内存的一种方法是执行

for (auto i = v.begin(); i != v.end(); i++)
{
    delete *i; // deleting through the iterator - we're not deleting THE iterator
}

除了其他人已经解释过的关于迭代器的一般规则之外,在你放在那里的代码的情况下,迭代器是一个堆栈变量,其作用域是声明它的块的局部(这几乎总是你声明迭代器的方式),因此删除它并不比删除任何其他堆栈变量更有意义,因为当它超出作用域时被清理。你只在分配了new的东西上调用delete

这里也有些相关:您写了vector<int>* v = new vector<int>(),这意味着v是一个指针,并在"堆"(自由存储)上分配,因此您需要显式地删除它。但是在你的例子中,你只在本地使用v,所以你根本没有理由使用指针,你不应该使用一个。只需编写std::vector<int> v;并直接使用它:it = v.begin(),就像@keyser解释的那样,就像您实际使用迭代器一样。当您这样做时,您不再调用delete v;, v将在超出作用域时自动清理,就像it现在被清理一样。

也许您需要阅读一些关于RAII的内容,这是优秀c++编程的基础之一。如果你有Java或Delphi或c#背景,这是一个新颖的概念,因为在这些语言中,你得到的都是对堆上对象的引用(或者编译器和运行时决定把它们放在哪里),但在c++中不是这样。您应该学会在c++代码中尽可能多地利用这个特性。在c++中,指向对象的指针应该是例外,而不是规则。