【问题标题】:Do items in a std::map stay at the same address forever?std::map 中的项目是否永远保持在同一个地址?
【发布时间】:2019-01-27 19:41:20
【问题描述】:

采取以下简单程序:

struct Foo
{
    int x;
    int y;
    int z;
    string s;
};

int main()
{
    Foo f1 = { 42,21,11, "Hello world" };
    std::map<int, Foo> foomap;

    foomap[400] = f1;
    Foo* ptr = &foomap[400]; // cache a pointer to the element we just inserted.

    cout << ptr->x << " " << ptr->y << " " << ptr->z << " " << ptr->s << std::endl;

    // fill the map up with a bunch of other random items at random indices   
    for (int x = 0; x < 10000; x++)
    {
        int i = rand();
        Foo f = { rand(), rand(), rand(), "Another string" };

        if (foomap.find(i) == foomap.end())
        {
            foomap[i] = f;
        }
    }

    Foo* ptr2 = &foomap[400];

    cout << "f1 insert location has " << ((ptr == ptr2) ? "not changed" : "changed") << std::endl;
    cout << ptr->x << " " << ptr->y << " " << ptr->z << " " << ptr->s << std::endl;

    return 0;
}

所以上面的程序缓存了一个指向地图中项目的指针。然后将更多的项目添加到地图中,然后验证第一个插入的项目是否已更改位置。

当我运行它时,我有些惊讶。缓存的指针保持不变:

42 21 11 Hello world
f1 insert location has not changed
42 21 11 Hello world

我会假设随着地图中项目数量的增长,实现可能会移动项目 - 就像 std::vector 绝对一样。

所以我的问题是:插入到地图中的项目是否保证在相同的地址,只要它没有从地图中删除或替换?还是这个实现是特定的?

【问题讨论】:

  • 所有基于节点的容器都是这样工作的。对容器的更改只是调整指针 - 它们不会在内存中移动东西。
  • @NeilButterworth - 它记录在任何地方?
  • @NeilButterworth - 什么定义了“基于节点的容器”。显然矢量不符合条件,但地图......
  • 任何像样的 C++ 教科书。
  • 我有很多不错的 C++ 教科书。像这样的细节通常不包括在内。 :)

标签: c++ std stdmap


【解决方案1】:

是的,地图上的插入/放置操作永远不会使迭代器或对现有项目的引用无效。

26.2.6 关联容器 [associative.reqmts]
9 insert 和 emplace 成员不应影响迭代器和对容器的引用的有效性,erase 成员应仅使迭代器和对已擦除元素的引用无效。

【讨论】:

  • 您是否偶然引用了证实这一点的参考资料或文档?
  • @selbie 添加了来自标准的引用
猜你喜欢
  • 2014-07-31
  • 2023-03-26
  • 1970-01-01
  • 2018-08-25
  • 2021-11-28
  • 1970-01-01
  • 2012-11-17
  • 1970-01-01
  • 2020-03-17
相关资源
最近更新 更多