(c++)内存四区:1.代码区2.全局区(静态区)3.栈区4.堆区
//内存四区:1.代码区 2.全局区 3.栈区 4.堆区
1.放在代码区的有:1.写的代码:只读的、共享的、存放的二进制机器指令、由操作系统直接管理
2.放在全局区的有:1.全局的(变量或常量) 2.静态的(变量或常量) 3.字符串常量
3.在栈区的有:1.局部的(变量或常量)
注:1.函数形参也是局部的 2.main()函数内创建的变量也是局部变量
3.对于一个局部变量指针,若它指向的空间在栈区,不要返回这个指针。由于变量是局部变量,函数结束后局部变量的就自动释放了,这块地址上的空间你也不能再操作了,除非你返回的这个地址在堆区。
对于一个局部变量指针,若它指向的空间在堆区,可以返回这个指针。虽然函数结束后这个指针同样会被释放,但是已经将地址传递出去了,并且由于他的地址在堆区所以虽然函数结束了但是这块空间依然能够被操作。
以上两种情况下在函数内创建的指针,在函数结束后都被释放了,只不过前者返回出来的地址不能用了,后者返回出来的地址仍然可以操控。
关键在于:指针指向的地址空间在栈区还是堆区,在栈区则不要返回(返回了也不能操纵,这块空间,因为编译器自动释放了)、在堆区则可以。
4.放在堆区的有:利用new创建的数据。可以通过delete释放
创建的操作为:
int* p2 = new int(10);
//new int(10)代表开辟一个堆区的空间并且赋值为10,整个表达式会返回这个空间的地址。
//int* p创建一个指针p。
//int* p=new int(10) 用创建的这个指针p来接收new int(10)返回的地址
以下代码在干嘛?在创建各种变量、常量、局部的、全局的、静态的,然后访问他们的内存地址。
注意!!!最后一个cout是为了演示delete后还要访问这个堆区的空间会引发的异常,读者使用代码时请给注释掉
#include<iostream>
using namespace std;
// 内存四区:1.代码区 2.全局区 3.栈区 4.堆区
//1.放在代码区的有:1.写的代码
//2.放在全局区的有:1.全局的(变量或常量) 2.静态的(变量或常量) 3.字符串常量
//3.在栈区的有:1.局部的(变量或常量),程序员创建,编译器自动释放
//4.放在堆区的有:1.new开辟的空间,由程序员创建和释放(整个程序运行完了也会自动释放)
//全局变量
int g_a = 0;
int g_b = 0;
//const修饰的全局变量
const int c_g_a = 0;
const int c_g_b = 0;
//static修饰的全局变量
static int s_g_a = 0;
static int s_g_b = 0;
int* func1()
{
int a = 10;
int* p1 = &a;
return p1;
}
//利用new将数据放在堆区
int* func2()
{
//new int(10)代表开辟一个堆区的空间并且赋值为10,整个表达式会这个空间的地址。
//int* p创建一个指针p。
//int* p=new int(10) 用创建的这个指针p来接收new int(10)返回的地址
int* p2 = new int(10);
return p2;
}
int main()
{
//全局变量
cout << "全局变量g_a的地址为:\t\t" << (int)&g_a << endl;
cout << "全局变量g_b的地址为:\t\t" << (int)&g_b << endl;
//静态变量 在普通变量前面加static,属于静态变量
static int s_a = 0;
static int s_b = 0;
cout << "静态局部变量s_a的地址为:\t" << (int)&s_a << endl;
cout << "静态局部变量s_b的地址为:\t" << (int)&s_b << endl;
//
cout << "静态全局变量s_g_a的地址为:\t" << (int)&s_g_a << endl;
cout << "静态全局变量s_g_b的地址为:\t" << (int)&s_g_b << endl;
//常量分为1.字符串常量2.const修饰的变量
cout << "字符串常量的地址:\t\t" << (int)&"hello world" << endl;
//const修饰的变量:1.修饰全局变量 2.修饰局部变量
cout << "全局常量c_g_a的地址为:\t\t" << (int)&c_g_a << endl;
cout << "全局常量c_g_b的地址为:\t\t" << (int)&c_g_b << endl;
//修饰局部变量
cout << endl;
const int c_l_a = 0;
const int c_l_b = 0;
cout << "局部常量c_l_b的地址为:\t" << (int)&c_l_a << endl;
cout << "局部常量c_l_b的地址为:\t" << (int)&c_l_b << endl;
//创建普通局部变量
int a = 0;
int b = 10;
cout << "局部变量a的地址为:\t" << (int)&a << endl;
cout << "局部变量b的地址为:\t" << (int)&b << endl;
cout << endl;
//读取指向栈区空间指针的值(不能正常读取,部分编译器第一次可以正常读取,之后便不行了)
int* p1 = func1();
cout << "第一次读取指向栈区空间的指针的值:" << *p1 << endl;
cout << "第二次读取指向栈区空间的指针的值:" << *p1 << endl;
cout << endl;
//读取指向堆区空间指针的值
int* p2 = func2();
cout << "第一次读取指向堆区空间的指针的值:" << *p2 << endl;
cout << "第二次读取指向堆区空间的指针的值:" << *p2 << endl;
//delete这个指针后再访问
delete p2;
//注意这行代码会引发异常!!!!使用代码请注释掉下面这个cout
cout << "delete p2后读取指向堆区空间的指针的值:" << *p2 << endl;
system("pause");
return 0;
}
注意!!!最后一个cout是为了演示delete后还要访问这个堆区的空间会引发的异常,读者使用代码时请给注释掉
代码运行截图:
显然:
1.只要是带“全局”或者“静态”的都在一起,还有字符串常量也是。
2.只要是带“局部”的也都放在一起。
3.若局部变量指针指向的地址在栈区,则无法访问
4.若局部变量指针指向的地址在堆区,则能够正常访问
5.若将这个指针delete后便不能够正常访问了,也没有访问的权限。