分区作用
代码区
存储程序编译后的函数体二进制代码,操作系统进行管理。
函数在程序编译之后,存储于代码区,调用函数通常建立栈帧来保存参数和局部状态;机器指令仍从代码区域取出执行,不是把函数代码压入栈。
全局区
变量在程序编译阶段已经分配好内存空间并初始化,这块内存空间在程序的整个运行期间都存在,主要存放静态变量、全局变量和常量

栈区
由系统进行内存管理,主要存放函数的参数以及局部变量。在函数完成执行,系统自行释放,不需要用户管理。
堆区
由程序员进行分配和释放,若程序员不能释放,程序结束时由操作系统进行回收
内存中的数据残留
删除硬盘上面的数据只是释放掉自己对于某一块空间的使用权,内存也是如此。

指针
指针的使用
#include <iostream>using namespace std;
int main() { int a = 10; int* p = &a;
cout <<"内存地址:" << p << endl;
// 地址访问 cout << "*p的值:" << *p << endl; // 通过指针修改值 *p = 200; cout <<"*p的值:" << *p << endl;}空指针和野指针
空指针:没有存储任何的内存地址的指针变量,一般使用NULL或者nullptr
野指针:里面存储一个内存地址,但是这个地址指向的空间已经不存在了。
常量指针和指针常量
常量指针:指向常量的指针 const int * a
- 指向的空间值是不允许修改的
- 指针的指向可以修改
int a = 10; // 常量指针 const int* p = nullptr; p = &a;
// *p = 200; 无法通过指针修改值
// 但是可以修改指针的指向 int b = 20; p = &b;指针常量:int *const a
- 可以修改指向空间的值
- 但是无法修改指针的转向
int a = 10; int b = 20;
int* const p = &a; //*p = &b; // 无法修改指向 *p = 200; // 但是可以修改值函数中使用指针
#include <iostream>using namespace std;
void change(int num) { num = 100;}
int main() { int n = 10; change(n); cout << n << endl;}以上题为例,如果我们希望最后输出的是100,而不是10,应该如何处理?
指针按值传参会复制地址值。重新给函数里的指针赋值不会改变调用者的指针;通过
*p修改所指对象则能影响调用者的对象。需要修改调用者的指针本身时,要传指针的引用或二级指针,不是仅把参数改成 const 指针。
#include <iostream>using namespace std;
void change(int* num) { *num = 100;}
int main() { int n = 10; change(&n); cout << n << endl;}引用
变量名是一段连续内存空间的别名,是一个标号,程序中可以通过变量来申请并命名空间,通过变量的名字来使用变量空间
引用注意事项:
- &这里不是用于计算
- 类型标志符和目标类型必须要一致
- 声明引用变量的时候必须进行初始化
- 引用初始化后,地址不能改变
- 不能由NULL
- 看作是一个别名
int a = 10;// 引用int &b = a;
// 两个地址一样cout << &a << endl;cout << &b << endl;函数中使用引用
#include <iostream>using namespace std;
void swap(int num1, int num2) { int temp = num1; num1 = num2; num2 = temp;}
int main() { int num1 = 10; int num2 = 33;
swap(num1, num2); cout << "num1=" << num1 << "\tnum2=" << num2 << endl;}运行以上代码后,我们可以发现最后的值还是是num1=10,num2=33,但是很显然不是我们想要的
void swap(int& num1, int& num2) { int temp = num1; num1 = num2; num2 = temp;}引用的本质
引用是已有对象的别名,不能重新绑定;它与指针常量有相似的使用效果,但不是同一种类型。
int *const a = &b <====> int& a = b
常量引用
const int& a = 10; 一般在函数里面,不想形参修改实参的值
评论