C++范围for循环中使用const auto&与const auto遍历std::string的差异及输出异常原因咨询
C++范围for循环中使用const auto&与const auto遍历std::string的差异及输出异常原因咨询
嗨,这个问题其实涉及到范围for循环中引用和值拷贝的本质差异,还有std::cout处理char*类型的特殊逻辑,咱们一步步拆解来看:
第一个代码块(使用const auto& item)
先看你这段代码:
#include "iostream" int main() { std::string s = "abc"; for ( const auto& item : s ) { std::cout << &item << std::endl; } }
这里的item是引用类型,它直接绑定到std::string s内部存储的每个字符上。因为std::string的字符是连续内存存储的,所以:
- 第一次循环时,
&item取的是s中第一个字符'a'的地址,也就是整个字符串的起始地址。std::cout遇到char*类型时,会把它当成C风格字符串的起始指针,从该地址开始输出直到遇到'\0',所以输出abc; - 第二次循环时,
&item取的是s中第二个字符'b'的地址,从这里开始输出到'\0',结果是bc; - 第三次循环同理,取的是
'c'的地址,输出c。
第二个代码块(使用const auto item)
再看这段代码:
#include "iostream" int main() { std::string s = "abc"; for ( const auto item : s ) { std::cout << &item << std::endl; } }
这里的item是值拷贝类型,每次循环都会创建一个新的临时对象,把s中当前字符的值拷贝到这个临时对象里。此时&item取的是这个临时对象的内存地址:
- 第一次循环时,临时对象里存的是
'a',但这个对象只有单个char大小,后面的内存区域是未初始化的垃圾数据。std::cout依然把&item当成C风格字符串指针,从这个地址开始输出直到遇到'\0',所以第一个字符是正确的'a',但后面会跟着一堆随机的“奇怪字符”; - 后续循环同理,每次的临时对象地址可能不同,输出的都是当前字符加后面的垃圾数据,这属于C++中的未定义行为,因为访问了未初始化的内存。
核心差异总结
const auto& item:item是原字符串字符的引用,&item指向原字符串的有效内存区域,cout能正确输出从该位置开始的剩余字符串;const auto item:item是原字符的临时拷贝,&item指向只存了单个字符的临时对象,后续内存无有效数据,cout输出时会越界读取垃圾内容,导致异常输出。
备注:内容来源于stack exchange,提问作者jurkDang
相关产品推荐
相关产品推荐

