swap 会导致string迭代器失效的疑惑
2022.4.8
标准库函数swap可以交换顺序容器元素,
对于vector,交换实际上并没有进行内存的复制,只是交换了两个vector的begin指针,所以不会导致原本的迭代器失效,但是原本指向v1的迭代器在交换后指向了v2,
对于string,string的基本实现有2种,
一,一个指向字符串begin的指针+一个表示字符串长度的整形+一个当前string已分配空间大小的整形
二,三个指针,分别指向,字符串begin,字符串end,当前已分配空间end
实测代码发现,swap并没有交换string的begin指针,而是进行了内存的交换,
为啥呢
2022.4.8
string在标准里有 短字符串优化(Short String Optimization,简称SSO)的做法
小于一定字符长度的string会直接储存在栈上而不是堆中,为了减少访问开销, 这个长度具体取决于实现,msvc的默认长度是15
而如果s1有优化指向栈,s2无优化指向堆,交换元素的时候,考虑到交换结果,s1要重新定位到堆上,所以此时s1会销毁之前栈上的空间,此举显然会导致之前s1的迭代器失效,
而对于s2,重新定位到栈上,就得重新在栈上开辟空间,但之前堆上的空间会被s1利用,不会销毁,
如下图所示,swap过后,s2一开始指向的堆空间依然存在,s1一开始的栈空间被释放,所以s2的迭代器依然有效,能够访问,此时访问s1迭代器会运行错误,提示迭代器失效
实测都在堆上的string交换不会导致迭代器失效,这显然合理,此时的交换仅仅同vector的交换操作,仅仅是交换begin指针
都在栈上的string交换会导致所有迭代器失效,这点我认为是默认情况下,栈上的string在做交换时一定会销毁当前空间再开辟新空间存放交换后的数据,但这个需要通过源码确认,待补充