在C 中将指针固定为迭代器是否安全

Is it safe to hold pointers to iterators in C++?

本文关键字:迭代器 是否 安全 指针      更新时间:2023-10-16

我将首先提出问题,然后将动机和动机提出,最后是汇编和执行预期的说明性代码样本。

问题

如果我可以向自己保证,迭代器在我需要使用时不会在持续时间内无效,那么将指针固定到迭代器的指针是安全的(例如,指向list<int>::iterator的指针)。

)。

动机

我有多个容器,我需要从一个容器中存放在一个容器中的物品中的直接交叉引用到另一个容器中的相应项目等。一个容器中的一个项目可能并不总是在另一个容器中具有相应的项目。

因此,我的想法是在存储在容器#1中的元素中等元素中,将迭代器的指针存储到元素中。为什么?因为一旦有一个迭代器,我不仅可以在容器#2中访问元素,而且可以在需要时,我还可以在容器#2等中删除元素。

如果容器#2中有一个相应的元素,我将在容器#1中存储一个指向迭代器的指针。否则,该指针将设置为空。现在,我可以快速检查一下,如果指向迭代器的指针为null,则在容器#2中没有相应的元素,如果非null,我可以继续访问它。

那么,以这种方式将指针存储到迭代器上是安全的吗?

代码样本

#include <iostream>
#include <list>
using namespace std;
typedef list<int> MyContainer;
typedef MyContainer::iterator MyIterator;
typdef MyIterator * PMyIterator;
void useIter(PMyIterator pIter)
{
    if (pIter == NULL)
    {
    cout << "NULL" << endl;
    }
    else
    {
    cout << "Value: " << *(*pIter) << endl;
    }
}
int main()
{
    MyContainer myList;
    myList.push_back(1);
    myList.push_back(2);
    PMyIterator pIter = NULL;
    // Verify for NULL
    useIter(pIter);
    // Get an iterator
    MyIterator it = myList.begin();
    // Get a pointer to the iterator
    pIter = & it;
    // Use the pointer
    useIter (pIter);
}

迭代器通常按值处理。例如,begin()end()将返回类型iterator的实例(对于给定的迭代器类型),而不是iterator&,因此它们每次都返回值的 copies

您当然可以获取此副本的地址,但是您不能指望对begin()end()的新调用将返回具有相同地址的对象,并且只要您握住迭代器对象,地址才有效你自己。

std::vector<int> x { 1, 2, 3 };
// This is fine:
auto it = x.begin();
auto* pi = &it;
// This is not (dangling pointer):
auto* pi2 = &x.begin();

保持迭代剂的指针很少有意义:迭代器已经是轻量级处理数据。进一步的间接通常是设计不良的迹象。在您的示例中,指针没有意义。只需通过普通迭代器即可。

迭代器的问题在于,容器上有很多操作使它们无效(这取决于所讨论的容器)。当您将迭代器固定到属于另一个类的容器时,您永远不会知道何时发生这种操作,并且没有简单的方法可以发现迭代器现在无效。

此外,直接删除属于另一个类的容器中的元素是违反封装原理的行为。当您想删除其他类的数据时,应该最好调用该类的公共方法,然后删除数据。

是的,只要您可以确保迭代器不会无效并且不会脱离范围。

听起来可怕。迭代器是一个对象,如果它离开范围,则指针无效。如果您在容器#2中删除一个对象,则所有迭代器都可能无效(取决于容器),因此您的指针变得毫无用处。

为什么不存储迭代器本身?对于1个没有指任何内容的容器中的元素,请存储container2.end()。只要迭代器没有无效,这就是可以的。如果是,您需要重新生成映射。

是的,可以像其他类型一样在迭代器上处理指针,但在您的示例中,这不是必需的,因为您可以简单地将原始迭代器作为参考传递。

通常,存储迭代器并不是一个好主意,因为在修改容器时,迭代器可能会变得无效。最好将容器存储并在需要时创建迭代器。