我打算在我的代码中使用std :: list,我决定不使用std :: forward_list,因为对于删除(我想),整个列表必须遍历,对于std :: O(N)的复杂性forward_list(作为单个链接列表)。但是,当我查看文档时,我注意到两个stl容器都有O(N)复杂性来删除项目。
然后我研究了“擦除”和“擦除_后”方法,它们的复杂性是“删除的元素数量的线性(破坏)”。这是因为,我将迭代器传递给节点(有点像“指针”)。但是,我不能(或者不想)在我的代码中传递这个迭代器来访问节点中的数据。如果列表被修改,我不确定这个迭代器是否有效?想法?
我的问题是,有没有办法可以获得指向列表中节点的指针。这样,我知道它将在我的程序的整个生命周期内有效,传递它。我可以调查它以访问我的数据。
答案 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
的
答案 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.