思念是想要穿越时间,去看看过去的你。
可我们谁都没有时光机,只能深夜对自己说
C++内存大致分为四个区域:
C++在运行前分为全局区和代码区
1.代码区,存放程序的二进制代码,操作系统自行管理这部分内存,这部分内存有两个特性-只读和共享,前者是为了防止程序意外修改了机器指令,后者是为了让那些频繁被执行的程序,在内存中只有一份代码。
2.全局区,存放全局变量、静态变量、字符串常量和const修饰的全局常量。
C++程序运行过后增加了栈区和堆区
3.栈区,编译器自行分配释放,存放函数的参数值和局部变量等。(实参和形参:形参是函数定义的参数,是一个占位符,用于接收函数调用时传进来的实参;实参时函数调用时传递进来的的具体的参数值,用于向函数传递数据)。
函数使用时不要返回局部变量的地址,局部变量的生命周期与其所在的函数一致,使用后函数运行结束时后会被销毁。
4.堆区,由程序员自己分配释放(通过new(C++)、malloc(C)等),程序结束时由操作系统回收。
#include <iostream>
using namespace std;
#include <string>
int c_1 = 10;
static int c_2 = 10;
const int c_5 = 10;
int* test()
{
int m = 20;
return &m;
}
int main()
{
int c_3 = 10;
static int c_4 = 10;
const int c_6 = 10;
cout << "局部变量c_3地址 " << (int)&c_3 << endl;
cout << "const修饰局部常量c_6地址" << (int)&c_6 << endl;
cout << "const修饰全局常量c_5地址" << (int)&c_5 << endl;
cout << "全局变量c_1地址 " << (int)&c_1 << endl;
cout << "静态全局变量c_2地址 " << (int)&c_2 << endl;
cout << "静态局部变量c_4地址 " << (int)&c_4 << endl;
cout << "字符串常量地址 " << (int)&"hello" << endl;
int* p=test();
cout << *p << endl;//编译器会默认保存一次
cout << *p << endl;//vs2022,x64调试中,局部变量的值会一直保存(疑惑),x86是此处位乱码
cout << *p << endl;
system("pause");
return 0;
}
图一为VS2022的x86调试结果,图二为VS2022的x64调试结果。
此处编译结果中对于局部变量作为函数的返回值,在VS2022的X64中三次输出均为20,是否意味着局部变量未被销毁,如果有大佬看到望解惑。
new与malloc
malloc:
函数声明:void *malloc(int size)
例:int *p=(int *)malloc (sizeof(int));
free(p);
malloc函数返回的时确定类型的指针,返回前需要进行强制类型转换。
malloc函数只管分配内存,不仅从初始化,传入的参数为分配内存的字节大小。
new:
格式:new 数据类型(初始化值)//返回一个同类型指针;
new 数据类型[大小] {初始化值};
delete 指针;
delete[ ]数组名;
#include <iostream>
using namespace std;
#include <string>
int* test()
{
int* a = new int(10);
return a;
}
int main()
{
int* p = test();
cout << *p << endl;
cout << *p << endl;
cout << *p << endl;
int* arr = new int[10] ;
for (int i = 0;i< 10;i++)
{
arr[i]=i+100;
}
for (int i = 0; i < 10;i++)
{
cout << arr[i] << endl;
}
delete p;
delete[]arr;
system("pause");
return 0;
}
上述结果中指针p解引用后值均为10,这是因为在测试函数中通过new关键字开辟的存放10的空间在堆区,不会随着函数的结束而销毁,p接收的这段空间的地址,尽管指针a被销毁了,但是其值传递给了p,也就是在堆区开辟的空间地址被传递给了p。