首页 > 解决方案 > 在我的代码中使用指向 STL 容器元素的指针?

问题描述

将某个类的元素存储在标准容器中,然后让其他一些类存储指向它们的指针是一个好主意/风格吗?

假设我有课程Astd::set<A>. 然后我创建B具有A*成员的类,并且该指针指向A集合中的一些。这可以保证在标准库中工作吗?和怎么std::map样?std::unordered_setstd::unordered_map

例如:

class A {};
std::set<A> set; //then fill with some elements

class B{
    A* a;
};

B b;
B.a = &(*set.begin());

标签: c++stl

解决方案


毫无疑问,检查文档是个好主意。

例如std::set插入

没有迭代器或引用无效。如果插入成功,则在节点句柄中保存的元素的指针和引用无效,并且在提取之前获得的对该元素的指针和引用变为有效。(C++17 起)

可以读取类似的擦除

对已擦除元素的引用和迭代器无效。其他引用和迭代器不受影响。

因此,从此(以及其他函数的文档)可以安全地得出结论,只要您不从集合中删除元素,就可以使用引用(和指向元素的指针)。

如果我们对 unordered_set 进行相同检查:插入

如果由于插入而发生重新散列,则所有迭代器都将失效。否则迭代器不受影响。引用不会失效。仅当新元素数大于 max_load_factor()*bucket_count() 时才会发生重新散列。如果插入成功,则在节点句柄中保存的元素的指针和引用无效,并且在提取之前获得的对该元素的指针和引用变为有效。(C++17 起)

擦除也一样:

对已擦除元素的引用和迭代器无效。其他迭代器和引用不会失效。

所以在这里我们也可以得出结论,只要元素存储在 unordered_set 中,获取指向元素的指针应该是安全的。

我将 unordered_map 留给您验证,但是由于 std::unordered_set 是 std::unordered_map 的一个特例,没有值,我希望它的行为类似。

编辑:这是否是一个好主意很难说。容器带有保证和要求。如果这些符合您的用例,那么值得一试。根据我的经验,我建议使用特定名称将这些东西封装在某个类中,并公开您需要使用的东西。这样,如果您决定更改实施,您就会知道您提供了什么以及不需要什么。


推荐阅读