为什么C++中const char*与const char[]的内存和指针行为差异巨大?
问题1解答
你第一个版本的范围for循环用的是值传递遍历,每次迭代都会在栈上创建一个StrStruct的临时副本strStructEle,这个临时变量的生命周期仅为当前循环迭代:
- 每次迭代结束后临时变量被销毁,下一次迭代会复用同一块栈内存创建新的临时副本,所以你打印的所有数组地址都是同一个
[address#99] - 你往
strListCopy里存的是临时副本里数组的首地址,迭代结束后这个地址就成为悬空指针,三次迭代后这块栈内存最后存储的是第三次迭代的"ga",后续遍历读取悬空指针时自然拿到的都是ga
改成const StrStruct&引用遍历后,不会生成临时副本,直接引用strStructList向量中存储的原始元素,这些原始元素的生命周期和向量一致,你存的是原始元素内部数组的有效地址,自然不会出问题。
问题2解答
const char*和const char[]本质是完全不同的类型,你觉得用法一致是因为C++的数组隐式退化规则:在大多数场景下(比如赋值给指针、作为cout输出参数时),数组会自动转换成指向自身首元素的指针,才给了你二者等价的错觉:
const char[]作为结构体成员时,是把字符串的内容本身直接存储在结构体的内存空间里,属于结构体的一部分const char*作为结构体成员时,只是把字符串的内存地址存储在结构体里,字符串内容本身存在其他内存区域,不属于结构体的一部分
问题3解答
你把成员改成const char*后,结构体里存储的是字符串字面量的地址,而字符串字面量是存储在程序的只读数据段,生命周期覆盖整个程序运行周期:
- 即使你用值遍历生成临时结构体副本,复制的也只是指针的值(也就是字符串字面量的地址),你往
strListCopy里存的就是这个全局有效的字面量地址 - 临时结构体销毁只会释放指针变量本身的内存,不会影响指针指向的只读数据段的字符串内容,所以所有地址都是有效的,输出自然符合预期。
内容的提问来源于stack exchange,提问作者Jaxon
相关产品推荐
相关产品推荐

