首先本文的对象是这么一段代码:
char * getResult0()
{
char *s = "This is a string";
return s;
}
char * getResult1()
{
char s[] = "This is a string";
return s;
}
两段代码非常相似,但是函数getRsult0返回的是字面值字符数组,函数getResult1返回的是静态数组。静态数组在栈上面分配的,因此函数返回的时候,已经不存在了,返回的指针悬空,因此编译报错!但是getResult0编译运行完全没有问题,这与字符串字面值的特殊性有着重要的关系!
字符串字面常量不同于普通的局部变量,具有static duration lifetime,这整个程序的生命周期中都将存在
原文出自 : C99 standard 6.4.5/5 "String Literals - Semantics":
The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence.
为验证上面的结论,看一下代码:
#include<iostream>
#include<cstdlib>
#include<cstring>
using namespace std;
char * getResult()
{
//返回静态字符数组
char *s= "This is a string";
return s;
}
char * otherResult()
{
//返回动态分配字符数组
char *s = new char[17];
strcpy(s,"This is a string");
return s;
}
int main()
{
char *s = getResult();
cout << "Adress is : " << (int)s <<" Value is :"<<s <<endl;
char *t = otherResult();
cout << "Adress is : " << (int)t <<" Value is :"<<t <<endl;
char *k = "This is a string";
cout << "Adress is : " << (int)k <<" Value is :"<<k <<endl;
//局部变量
int a = 0;
cout << "Adress is : " << (long)&a <<" Value is :"<<a <<endl;
//局部指针变量
int *b = new int(0);
cout << "Adress is : " << b <<" Value is :"<<*b <<endl;
//
system("pause");
return 0;
}
其执行结果如下:
Adress is : 1734656 Value is :This is a string
Adress is : 2249944 Value is :This is a string
Adress is : 1734656 Value is :This is a string
Adress is : 4520584 Value is :0
Adress is : 00225528 Value is :0
请按任意键继续. . .
不同机器上执行的地址是不同的!每次运行相同的程序结果也会有差异。
s和k的地址是相同的,因为内容完全相同,这就说明返回字符串字面常量的时候,该字面常量是在一段特殊的区域叫只读存储区分配的,不同于普通的静态数组和内置类型,这些在栈上面分配,并且有编译器去管理释放。
C++返回指针,不能返回指向局部对象的指针!!!但是字符串字面常量不是局部对象,而是在整个程序生命周期中都存在的静态常量。因此可以返回指向该地址的引用!明显可以看出,a,b,k,t内存区域都相差很大,因为他们作用域不同。通过这些结果能够大致了解C++字面字符串常量!
t是动态分配的,不是常量,是堆上分配的空间。堆上面分配的空间和普通类型的局部变量的生命周期是不一样的,须有程序员主动的释放。
给一条stackoverflow上面的问答链接,感兴趣的可以看看: