【问题标题】:Is std::string::begin() iterator invalid after += operator?+= 运算符后 std::string::begin() 迭代器是否无效?
【发布时间】:2021-10-21 03:13:10
【问题描述】:

在调试我的代码时,我注意到存储迭代器发生了变化,指向 begin(),在每 4 或 5 次调用字符串上的 += 运算符之后(它指向的内容甚至不在字符串中)本身!)。这是我的代码的样子:

for (auto ch=word.begin(); ch!=word.end(); ++ch) {
  // on a condition, the following loop starts
  // ch == word.begin()
  for (int i=0; ...) {
    string_view tmp = arr[i];
    word += tmp;
  }
  // ch is no longer equal to word.begin()
}

虽然在第二个循环解决了我的问题后将 ch 重新分配给 word.begin(),但我想知道为什么会发生这种情况。我在互联网上找不到任何东西。

【问题讨论】:

  • 在迭代字符串时不能修改字符串,因为这些修改可能会导致底层存储被重新分配(使任何迭代器失效)。
  • 如果/当重新分配字符串时,所有指向基础数据的迭代器/指针都将失效。
  • 问问自己:如果数组始终是固定大小的,并且单词的大小在增加,当它需要变得比它使用的数组更大时会发生什么?
  • 我可以看到 OPs 问题,在这两个页面中搜索 invalid std::string::clearstd::string::operator+= 大部分修改操作都缺少失效子句。
  • “我在互联网上找不到任何东西。”真的吗?当我从字面上复制并粘贴您的问题标题into a search engine 时,second result I get 显示了一个问题示例(由推回向量引起,这基本上是相同的情况)并附有详细说明.或者你可以尝试类似[c++ tutorial iterator invalidation](duckduckgo.com/?q=c%2B%2B+tutorial+iterator+invalidation)。

标签: c++ c++17 stdstring


【解决方案1】:

当您扩展诸如向量或字符串之类的硬币容器时,有时它们可​​能会将其内存重新分配到新位置-因此它会更改地址。它们需要连续的内存,因为没有指向下一个元素的列表。

迭代器在连续的内存地址中移动。下一个元素是地址+1。

因此,在开始时,字符串中的第一个元素存储在地址 X 中。但是添加了几个字母,这导致将容器重新分配到新位置。现在,您的字符串不是存储在地址 X 中,而是地址 Y。尽管如此,您的迭代器仍然指向地址 X。

在添加或删除元素时,您不能在不重新初始化的情况下使用迭代器,因为这些操作会导致迭代器失效。

【讨论】:

  • "...因为这些操作会导致迭代器失效"...不,这并不总是正确的,这是一个概括。有容器特定的规则/条件/等:see a list here。 (虽然那里没有提到std::string...)
猜你喜欢
  • 2015-04-29
  • 2011-05-06
  • 1970-01-01
  • 2016-02-12
  • 2021-09-24
  • 2020-10-05
  • 1970-01-01
  • 1970-01-01
  • 2011-09-19
相关资源
最近更新 更多