获取std :: list或std :: forward_list中节点的指针

时间:2014-02-21 00:23:36

标签: c++ pointers stl

我打算在我的代码中使用std :: list,我决定不使用std :: forward_list,因为对于删除(我想),整个列表必须遍历,对于std :: O(N)的复杂性forward_list(作为单个链接列表)。但是,当我查看文档时,我注意到两个stl容器都有O(N)复杂性来删除项目。

经过一番思考,我弄清楚了为什么(我认为)。这是因为在这两种情况下,必须首先扫描整个列表以找到该节点,然后将其删除。这是对的吗?

然后我研究了“擦除”和“擦除_后”方法,它们的复杂性是“删除的元素数量的线性(破坏)”。这是因为,我将迭代器传递给节点(有点像“指针”)。但是,我不能(或者不想)在我的代码中传递这个迭代器来访问节点中的数据。如果列表被修改,我不确定这个迭代器是否有效?想法?

我的问题是,有没有办法可以获得指向列表中节点的指针。这样,我知道它将在我的程序的整个生命周期内有效,传递它。我可以调查它以访问我的数据。

5 个答案:

答案 0 :(得分:3)

  

如果列表被修改,我不确定这个迭代器是否有效

是的,在一般情况下,存储迭代器是有风险的,除非您密切关注对容器执行的操作。

问题是,指针的只是相同的。实际上,对于许多容器,迭代器都是作为指针实现的。

因此,如果您愿意,可以存储迭代器或指针,但无论如何,请关注迭代器失效规则:

答案 1 :(得分:3)

  

但是,我不能(或者不想)在我的代码中传递这个迭代器来访问节点中的数据。

为什么不呢?迭代器易于使用且非常轻巧。指针在任何方面都不是更好。

  

如果列表被修改,我不确定这个迭代器是否有效?

对于list,即使修改了列表,任何迭代器都将保持有效。 除了,当然,如果你删除了迭代器所指向的特定元素。但这很明显,你可以'期望有一个迭代器(或指针)到不再存在的东西。

vector更危险。对向量的一个小改动可能使其所有迭代器无效。)

您可以在list中指向任何单个元素

list<int> iterator it = find(l.begin(), l.end(), 7); // get an iterator
int * ptr = &*it; // get a pointer to the same element.

指针在很多方面类似于迭代器。但迭代器更强大一些。迭代器可以递增或递减,以访问列表中的相邻元素。迭代器可用于从列表中删除元素。指针无法执行这两种操作。

只要不删除该特定元素,迭代器和指针都保持有效。

答案 2 :(得分:2)

对于列表,即使列表中的其他项被删除,迭代器也是有效的。当删除列表中迭代器引用的项时,它变为垃圾。

所以,只要你知道你传递的迭代器并没有被其他代码删除,它们就可以安全地保留。这看起来很脆弱。

即使在迭代器之外有一个构造来引用列表中的节点,它也会遭受同样的脆弱性。

但是,您可以让每个节点对其存储的数据包含std::shared_ptr而不是对象本身,然后将std::weak_ptr传递给这些对象并检查expired之前访问那些weak_ptr

例如

而不是

std::list<MyClass> foo;

你会有

std::list<std::shared_ptr<MyClass>> foo;

查看有关weak_ptr

信息的here

答案 3 :(得分:0)

  

有没有办法可以获得指向列表中节点的指针

,在您的特定实施中。

,符合标准的方式。

如果查看std::list documentation,则没有关于节点的单词。虽然除了使用双向链接列表之外,很难想象实现std::list的不同方式,但没有任何方法可以阻止它。

几乎从未未记录的库内部进行任何联系。

答案 4 :(得分:0)

  

在列表中或在多个列表中添加,删除和移动元素不会使迭代器或引用无效。仅当删除相应的元素时,迭代器才无效。

来源:https://en.cppreference.com/w/cpp/container/list

因此std::list<>::iterator 仅在删除相应元素时才无效。因此,是的,只要确保存在相应的元素(在存储/传递指向任何对象的指针的情况下无论如何都必须这样做),就可以在整个生命周期中保存和/或传递迭代器程序。

现在,迭代器不过是伪装的指针。因此,如果您希望保存/传递相应的 pointer 而不是迭代器,则始终可以按照@Aaron McDaid的建议,首先将迭代器转换为指针。

int * ptr = &*it; // get a pointer to the same element.