调用std::string的+=运算符后,其begin()返回的迭代器是否会失效?
这问题其实是C++里std::string迭代器失效的典型场景,我给你拆解清楚:
首先得明白std::string的底层实现:它本质是个动态扩容的字符数组。默认情况下,它会先分配一块初始内存,当你用+=不断追加内容时,如果当前剩余的内存空间不够装下新内容,string就会触发「内存重分配」——找一块更大的新内存,把原来的所有字符拷贝过去,然后释放掉旧的内存块。
回到你的代码:
for (auto ch=word.begin(); ch!=word.end(); ++ch) {
// 在满足某个条件时,启动以下循环
// 此时ch == word.begin()
for (int i=0; ...) {
string_view tmp = arr[i];
word += tmp;
}
// 此时ch不再等于word.begin()
}
你一开始让ch指向word.begin(),也就是旧内存块的起始地址。当第二个循环里的+=操作次数足够多,触发了string的扩容后,word的底层数组已经换成了新的内存地址,而旧内存已经被释放或者不再属于这个string了。这时候ch还死死盯着旧内存的位置,自然就变成了无效迭代器——它指向的地址已经不属于当前word的内存范围,甚至可能是已经被系统回收的垃圾内存。
你后来把ch重新赋值为word.begin()能解决问题,是因为这时候获取的是新内存块的起始地址,迭代器重新变得有效了。
额外提一句:不止是begin()迭代器,所有在扩容前获取的迭代器、指针、引用都会失效。所以只要对string做了可能触发扩容的操作(比如+=、append、insert等),之前保存的迭代器就不能再用了,必须重新获取。
内容的提问来源于stack exchange,提问作者etzl

