在使用std::for_each() 遍历同一个std::map的过程中向该map插入新元素,是否可能导致潜在的段错误(如果发生重新分配的话)?

前端开发 2026-07-09

因此,在我用C++11编写、用于AEC到 WebAssembly的编译器中,我有这段代码:此处代码链接:

if (!staticPropertiesInitialized) { // https://atheistforums.org/thread-63150-post-2055509.html#pid2055509
      basicDataTypeSizes["Integer32"] = 4;
      basicDataTypeSizes["Character"] = 1;
      basicDataTypeSizes["Decimal32"] = 4;
      basicDataTypeSizes["Integer64"] = 8;
      basicDataTypeSizes["Decimal64"] = 8;
      basicDataTypeSizes["Integer16"] = 2;
      std::for_each(basicDataTypeSizes.begin(), basicDataTypeSizes.end(),
                    [&](std::pair<std::string, int> type) {
                      if (not(isPointerType(type.first)))
                        basicDataTypeSizes[type.first + "Pointer"] =
                            4; // JavaScript (WebAssembly) virtual machine is
                               // 32-bit (pointers being 32 bits or 4 bytes
                               // long), unless somebody switches to the 64-bit
                               // mode (which is almost never done).
                    });
      basicDataTypeSizes["Nothing"] = 0;
}

现在,显然,如果 basicDataTypeSizes 是一个 std::vector,在对它进行遍历的同时修改容器的大小(使用一个 std::for_each 来实现)在循环过程中发生重新分配的极不可能的情形时,这段代码可能会导致段错误。但是 basicDataTypeSizes 当然是一个 std::mapstd::map 本质上是一个红黑树,其节点在修改 std::map 时本不应被重新分配……还是会呢?

我用来测试这段代码的编译器没有发出任何警告。

解决方案

在遍历一个 std::map 的同时修改它,不会使迭代器失效

具体来说,对于你使用的 operator[],它在 cppreference文档 中有说明:

没有迭代器或引用会失效。

(其他 std::map 修改方法也保证迭代器的有效性——参见例如 std::map::insertstd::map::emplace 等。)

因此就这一点来说,你的代码是有效的。

注:
正如Igor commented 所述,在当前遍历过程中并不保证新添加的元素会被访问到。但在这种情况下似乎并不重要。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章