首先从一个现象出发:
代码段1:
char a[] = "sdf"; a[0] = 'a'; cout << a;
char *a = "sdf"; a[0] = 'a'; cout << a;
要解释上面的不同结果,必须了解一下C++的存储区。C++在运行程序时,在内存中有5块不同的区域来存储数据,分别为栈、堆、全局\静态区、常量区、代码区。
栈:由程序自动分配并且释放,多用来存储局部变量、函数参数,在函数调用时使用。
堆:由程序员分配并且释放,在C中由malloc创建,在C++中由new创建。只能通过指针访问。
全局\静态区:存放程序的全局变量和静态变量。在C中,初始化的变量和未初始化的变量分开存放,在C++中,存放在一起。
常量区:1、存放被const修饰的变量。
2、存放类似“123456”这样的字符串字面值。
代码区:存放程序的二进制代码。
代码段1中,“sdf”字面值存储在常量区,字符数组a存储在栈中,并且将字面值“sdf”也拷贝了一份存储在栈中。第2行改变字符数组的首元素时,修改了存储在栈中的元素,因此修改成功。
代码段2中,“sdf”字面值存储在常量区,字符指针存储在栈中,但是该指针指向的是常量区的“sdf”。第2行设法改变常量区的字符串常量,就会出现访问内存错误。抛出runtime error。
1、栈和堆的区别在于栈是由程序自动分配和释放,堆是由程序员通过代码显式分配和释放。栈和堆中的元素都是可以通过代码修改的。除了new出的空间,大部分变量存在栈中。这些变量都有明确的大小,一个紧接着一个排列在栈中。
2、数组之所以必须指定其大小,就是因为数组要存储在栈中,由程序自动分配和释放,必须明确知道大小。通过new分配的空间在堆中,大小可以在程序运行时指定。
3、指针不一定都是通过new创建的指向堆的,比如代码片段2指向常量区的指针。
引用:
1、ChinaUnix [C] 请教下高手,char *str为什么会默认为 const char *str?
2、徐中 BizTalk 产品专家 [C++] 堆栈与堆的概念
3、csdn博客 Kaho的专栏 【C++】堆栈
4、百度知道 C++ const char* 指针相等问题
5、csdn博客 飞鸽沟通最简单 浅谈C/C++堆栈指引——C/C++堆栈很强大
6、C语言中文网 C++二维数组讲解、二维数组的声明和初始化