无法增加价值限制的地图/设置迭代器

发布于 2025-01-18 03:36:31 字数 631 浏览 4 评论 0 原文

我正在尝试在地图中的索引j之后增加节点的键,但是我在将迭代器递增到下一个节点时会遇到一些错误,这是我的代码:

typedef map<int, string> My_map;    
My_map my_map;
my_map[0] = "la base";
my_map[1] = "le premier";

int j = 1;

My_map::reverse_iterator first_it(my_map.rbegin());
first_it++;
My_map::reverse_iterator last_it(make_reverse_iterator(next(my_map.begin(), j - 1)));

for (My_map::reverse_iterator it = first_it ; it != last_it ; it++) {
    auto handle = my_map.extract(it.base());
    handle.key()++;
    my_map.insert(move(handle));
}

我知道地图不能具有重复的键,所以我开始从最后一个到j-th。但是 it ++ 不起作用。这与我使用 first_it ++; 时有所不同吗?

I'm trying to increment key of nodes after the index j in a map, but I got some error while incrementing the iterator to the next node, here's my code :

typedef map<int, string> My_map;    
My_map my_map;
my_map[0] = "la base";
my_map[1] = "le premier";

int j = 1;

My_map::reverse_iterator first_it(my_map.rbegin());
first_it++;
My_map::reverse_iterator last_it(make_reverse_iterator(next(my_map.begin(), j - 1)));

for (My_map::reverse_iterator it = first_it ; it != last_it ; it++) {
    auto handle = my_map.extract(it.base());
    handle.key()++;
    my_map.insert(move(handle));
}

I know that a map cannot have duplicate keys, so I started incrementing from the last one to the j-th one. But the it++ does not work. Is it different from when I used first_it++; ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

是你 2025-01-25 03:36:31

它提到了副作用:

提取节点仅使迭代器无效到提取的元素。指针和对提取元件的引用仍然有效,但在元素归节点句柄所有时不能使用:如果将元素插入到容器中,则将其可用。

如您所见,所有迭代器都可以找到除了您关心的迭代器外。因为 it 是提取元素的迭代器,所以它现在无效。随后的尝试使用它(使用 it ++ 推进循环迭代)会导致不确定的行为。

您可以做的是使用 std :: map :: insert

auto result = my_map.insert(move(handle));
it = make_reverse_iterator(result.position);

In the documentation for std::map::extract it mentions the side-effects:

Extracting a node invalidates only the iterators to the extracted element. Pointers and references to the extracted element remain valid, but cannot be used while element is owned by a node handle: they become usable if the element is inserted into a container.

As you can see, all the iterators are find except for the ones you care about. Because it is an iterator to the extracted element, it is now invalid. Subsequent attempts to use it (with it++ to advance the loop iteration) leads to undefined behavior.

What you can do is use the iterator returned by std::map::insert:

auto result = my_map.insert(move(handle));
it = make_reverse_iterator(result.position);
戒ㄋ 2025-01-25 03:36:31

正如 @paddy 所指出的,在调用 之后。 extract() 方法并再次执行 .insert() 你的所有迭代器都无效,因此你不能进一步运行修改循环。

我建议使用以下有效且更快的解决方案。复制到单独的 std::vector 中,复制从 j< 开始的所有元素/code>-第一个位置。在地图中删除它们。按照您喜欢的方式在向量中修改它们,例如向所有键添加 +1。通过地图的 .insert(begin, end) 方法一次性将它们全部插入回来。复制元素的清晰向量。

所有建议均在以下代码片段中实现:

在线尝试!

#include <map>
#include <string>
#include <vector>
#include <iostream>

int main() {
    std::map<int, std::string> m;
    m[0] = "la base";
    m[1] = "le premier";

    int j = 1;

    auto const j_it = std::next(m.begin(), j);
    std::vector<std::pair<int, std::string>> vcopy(j_it, m.end());
    m.erase(j_it, m.end());
    for (auto & [k, v]: vcopy)
        ++k;
    m.insert(vcopy.begin(), vcopy.end());
    vcopy.clear();

    // Show map
    for (auto const & [k, v]: m)
        std::cout << k << ": " << v << std::endl;
}

输出:

0: la base
2: le premier

As pointed by @paddy, after calling .extract() method and doing .insert() again all your iterators are invalidated hence you can't run modifying loop any further.

I suggest following solution which is valid and faster. Into separate std::vector copy all elements starting from j-th position. Delete them in map. Modify them in vector the way you like, for example by adding +1 to all keys. Insert them all back at once by .insert(begin, end) method of a map. Clear vector of copied elements.

All suggested is implemented in below code snippet:

Try it online!

#include <map>
#include <string>
#include <vector>
#include <iostream>

int main() {
    std::map<int, std::string> m;
    m[0] = "la base";
    m[1] = "le premier";

    int j = 1;

    auto const j_it = std::next(m.begin(), j);
    std::vector<std::pair<int, std::string>> vcopy(j_it, m.end());
    m.erase(j_it, m.end());
    for (auto & [k, v]: vcopy)
        ++k;
    m.insert(vcopy.begin(), vcopy.end());
    vcopy.clear();

    // Show map
    for (auto const & [k, v]: m)
        std::cout << k << ": " << v << std::endl;
}

Output:

0: la base
2: le premier
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文