为何构造函数中为指针赋值字符串安全?局部数组指针却有风险?
C++字符串字面量与局部数组的内存区别解答
先看你给出的代码:
.h 文件
class test { public: int Length; char* Name; int* ARR; test(int l, char* n, int* a); test(); };
.cpp 文件
test::test(int l, char* n, int* a){ Length=l; Name=n; ARR=a; }
main.cpp 文件
#include<iostream> void InAFunc(test *kio) { int foo[3] = { 1,2,3 }; *kio = test(7, "Hello!", foo); } int main() { test mmk; InAFunc(&mmk); std::cout << mmk.Name << mmk.ARR[1]; }
你的疑问是:明明访问mmk.ARR会因为局部变量foo被释放出问题,为什么给Name赋值字符串字面量却是安全的?
这得从C++里不同内存区域的特性说起:
字符串字面量的内存归宿
像"Hello!"这种字符串字面量,它并不是存放在函数的栈帧里,而是被编译器放在只读数据段(常量区)。这个区域的内存是在程序启动时就分配好的,并且会一直存在到整个程序运行结束才会被回收。所以当你把这个字符串的地址赋值给Name指针时,这个指针指向的是全局生命周期的内存,哪怕InAFunc函数执行完销毁了自己的栈帧,Name指向的字符串依然好好待在内存里,自然可以安全访问。局部数组
foo的内存归宿
而int foo[3]是函数InAFunc里的局部变量,它存放在栈内存中。栈内存的管理是跟着函数调用走的:函数执行时,栈帧被创建,局部变量在栈上分配空间;函数执行完毕,栈帧被销毁,栈上的局部变量内存会被标记为可复用(相当于被释放)。这时候mmk.ARR指向的就是已经被回收的栈内存,后续访问这个指针就属于“访问悬空指针”,会触发未定义行为(可能崩溃,也可能出现奇怪的结果)。
最后提个小建议:字符串字面量本质是const char[],虽然C++允许把它赋值给char*(兼容C的旧代码),但最好把test类里的Name声明为const char*,这样能避免不小心修改字符串字面量的风险(修改字符串字面量本身也是未定义行为)。
内容的提问来源于stack exchange,提问作者Dangee
相关产品推荐
相关产品推荐

