网站建设不能在淘宝发布,wordpress是什么平台,品牌策划公司业务范围,重庆市建设岗培中心网站内存分区、引用 文章目录 内存分区、引用前言1 内存分区模型1.1 程序运行前1.2 程序运行后1.3 new 操作符 2 引用2.1 引用基本使用2.2 引用注意事项2.3 引用做函数参数2.4 引用做函数返回值2.5 引用本质2.6 常量引用 总结 前言
本文包含内存分区、引用基本使用、引用注意事项、…内存分区、引用 文章目录 内存分区、引用前言1 内存分区模型1.1 程序运行前1.2 程序运行后1.3 new 操作符 2 引用2.1 引用基本使用2.2 引用注意事项2.3 引用做函数参数2.4 引用做函数返回值2.5 引用本质2.6 常量引用 总结 前言
本文包含内存分区、引用基本使用、引用注意事项、引用做函数参数、引用做函数返回值、引用本质、常量引用。 1 内存分区模型
C程序在执行时将内存大方向划分为4个区域
1、代码区存放函数体的二进制代码由操作系统进行管理的
2、全局区存放全局变量和静态变量以及常量
3、栈区由编译器自动分配释放存放函数的参数值局部变量等
4堆区由程序员分配和释放若程序员不释放程序结束时由操作系统回收
内存四区意义
不同区域存放的数据赋予不同的生命周期给我们更大的灵活编程
1.1 程序运行前
在程序编译后生成了exe可执行程序未执行该程序前分为两个区域
代码区
1、存放 CPU 执行的机器指令
2、代码区是共享的共享的目的是对于频繁被执行的程序只需要在内存中有一份代码即可
3、代码区是只读的使其只读的原因是防止程序意外地修改了它的指令
全局区
1、全局变量和静态变量存放在此
2、全局区还包含了常量区字符串常量和其他常量也存放在此
该区域的数据在程序结束后由操作系统释放
// c-const g-global l-local(局部)#include iostream // 包含标准输入输出流文件
using namespace std; // 使用标准命名空间// 全局变量
int g_a 10;
int g_b 10;// 全局常量
const int c_g_a 10;
const int c_g_b 10;int main() {// 局部变量int a 10;int b 10;// 打印地址cout 局部变量a地址为 (int)a endl; // 5961520栈区cout 局部变量b地址为 (int)b endl; // 5961508cout endl;cout 全局变量g_a地址为 (int)g_a endl; // 10272820全局区cout 全局变量g_b地址为 (int)g_b endl; // 10272824cout endl;// 静态变量在普通变量前面加static属于静态变量static int s_a 10;static int s_b 10;cout 静态变量s_a地址为 (int)s_a endl; // 10272828cout 静态变量s_b地址为 (int)s_b endl; // 10272832cout endl;// 字符串常量cout 字符串常量地址为 (int)hello world endl; // 10263396cout 字符串常量地址为 (int)hello world1 endl; // 10263404cout endl;// const 修饰的常量// const 修饰的全局常量cout 全局常量c_g_a地址为 (int)c_g_a endl; // 10264208cout 全局常量c_g_b地址为 (int)c_g_b endl; // 10264212cout endl;// const 修饰的局部常量const int c_l_a 10;const int c_l_b 10;cout 局部常量c_l_a地址为 (int)c_l_a endl; // 5961496栈区cout 局部常量c_l_b地址为 (int)c_l_b endl; // 5961484cout endl;system(pause); // 相当于在本地 Windows 调试器中的请按任意键继续...暂停方便看清楚输出结果return 0; // 程序正常退出
}1.2 程序运行后
栈区
1、由编译器自动分配释放, 存放函数的参数值,局部变量等
2、注意事项不要返回局部变量的地址栈区开辟的数据由编译器自动释放
#include iostream // 包含标准输入输出流文件
using namespace std; // 使用标准命名空间// 栈区数据注意事项不要返回局部变量的地址
// 栈区的数据由编译器管理和释放int* func(int b) // int类型的指针代表int类型的地址形参数据也会放在栈区
{b 100;int a 10; // 局部变量存放在栈区栈区的数据在函数执行完后自动释放return a; // 返回局部变量的地址
}int main() {// 利用指针接收func函数的返回值指针指向a数据地址int* p func(1);cout *p endl; // 10*解引用 // 第一次可以打印正确的数字是因为编译器做了保留cout *p endl; // 267955168(乱码) // 第二次这个数据就不再保留了system(pause); // 相当于在本地 Windows 调试器中的请按任意键继续...暂停方便看清楚输出结果return 0; // 程序正常退出
}堆区
1、由程序员分配释放,若程序员不释放,程序结束时由操作系统回收
2、在C中主要利用new在堆区开辟内存
#include iostream // 包含标准输入输出流文件
using namespace std; // 使用标准命名空间int* func()
{// 利用new关键字可以将数据开辟到堆区// 指针本质也是局部变量放在栈上指针保存的数据是放在堆区int* a new int(10); // 返回内存编号地址存放的也是地址new int(10)return a;
}int main() {int* p func();cout *p endl; // 10cout *p endl; // 10system(pause); // 相当于在本地 Windows 调试器中的请按任意键继续...暂停方便看清楚输出结果return 0; // 程序正常退出
}1.3 new 操作符
1、C 中利用 new 操作符在堆区开辟数据
2、堆区开辟的数据由程序员手动开辟手动释放释放利用操作符 delete
3、语法 new 数据类型
4、利用 new 创建的数据会返回该数据对应的类型的指针
示例1 基本语法
#include iostream // 包含标准输入输出流文件
using namespace std; // 使用标准命名空间int* func()
{// 利用new关键字可以将数据开辟到堆区// 指针本质也是局部变量放在栈上指针保存的数据是放在堆区int* a new int(10); // 返回内存编号地址存放的也是地址new int(10)return a;
}int main() {int* p func(); // 10cout *p endl; // 10cout *p endl; // 10// 堆区的数据由程序员管理开辟程序员管理释放delete p; // 利用delete释放堆区数据// cout *p endl; //报错释放的空间不可访问内存已被释放再次访问就是非法操作会报错system(pause); // 相当于在本地 Windows 调试器中的请按任意键继续...暂停方便看清楚输出结果return 0; // 程序正常退出
}示例2开辟数组
#include iostream // 包含标准输入输出流文件
using namespace std; // 使用标准命名空间int main() {int* arr new int[10]; // 10代表数组有10个元素for (int i 0; i 10; i){arr[i] i 100; // 给10个元素赋值 100~109}for (int i 0; i 10; i){cout arr[i] ;}cout endl;// 释放数组 delete 后加 []delete[] arr;cout endl;system(pause); // 相当于在本地 Windows 调试器中的请按任意键继续...暂停方便看清楚输出结果return 0; // 程序正常退出
}2 引用
2.1 引用基本使用
**作用 ** 给变量起别名
语法 数据类型 别名 原名 #include iostream // 包含标准输入输出流文件
using namespace std; // 使用标准命名空间int main() {int a 10;// 数据类型 别名 原名int b a;cout a a endl; // 10cout b b endl; // 10b 100;cout a a endl; // 100cout b b endl; // 100cout endl;system(pause); // 相当于在本地 Windows 调试器中的请按任意键继续...暂停方便看清楚输出结果return 0; // 程序正常退出
}2.2 引用注意事项
1、引用必须初始化
2、引用在初始化后不可以改变 #include iostream // 包含标准输入输出流文件
using namespace std; // 使用标准命名空间int main() {int a 10;int b 20;// int c; // 错误引用必须初始化int c a; // 一旦初始化后就不可以更改c b; // 这是赋值操作不是更改引用cout a a endl; // 20cout b b endl; // 20cout c c endl; // 20cout endl;system(pause); // 相当于在本地 Windows 调试器中的请按任意键继续...暂停方便看清楚输出结果return 0; // 程序正常退出
}2.3 引用做函数参数
作用 函数传参时可以利用引用的技术让形参修饰实参
优点 可以简化指针修改实参
#include iostream // 包含标准输入输出流文件
using namespace std; // 使用标准命名空间// 1、值传递
void mySwap01(int a, int b) {int temp a;a b;b temp;
}// 2、地址传递
void mySwap02(int* a, int* b) { // 传值使用取值符接收时用指针*int temp *a;*a *b;*b temp;
}// 3、引用传递
void mySwap03(int a, int b) { // 引用a相当于实参a的别名别名与原名一致修改别名a就相当于修改aint temp a;a b;b temp;
}int main() {int a 10;int b 20;mySwap01(a, b); // 值传递形参不会修饰实参cout a: a \tb: b endl; // a:10 b:20mySwap02(a, b); // 地址传递形参会修饰实参cout a: a \tb: b endl; // a:20 b:10mySwap03(a, b); // 引用传递形参会修饰实参cout a: a \tb: b endl; // a:20 b:10 因为mySwap02()将实参修改了在mySwap02()的基础上再进行更换cout endl;system(pause); // 相当于在本地 Windows 调试器中的请按任意键继续...暂停方便看清楚输出结果return 0; // 程序正常退出
}2.4 引用做函数返回值
作用 引用是可以作为函数的返回值存在的
注意 不要返回局部变量引用
用法 函数调用作为左值
#include iostream // 包含标准输入输出流文件
using namespace std; // 使用标准命名空间// 返回局部变量引用
int test01() {int a 10; // 局部变量存放在四区中的栈区函数调用后将被释放return a;
}// 返回静态变量引用
int test02() {static int a 20; // 静态变量存放在全局区全局区上的数据在程序结束后系统释放return a;
}int main() {// 不能返回局部变量的引用int ref test01();cout ref ref endl;cout ref ref endl;int ref2 test02();cout ref2 ref2 endl; // 20cout ref2 ref2 endl; // 20// 如果函数做左值那么必须返回引用// 如果函数的返回值是引用这个函数调用可以作为左值test02() 1000; // test02()调用后返回的是a的引用相当于返回a这个变量test02()返回的就是a的本身相当于a1000cout ref2 ref2 endl; // 1000 ; ref2是a的别名原名赋值为1000使用别名ref2访问也是1000cout ref2 ref2 endl; // 1000cout endl;system(pause); // 相当于在本地 Windows 调试器中的请按任意键继续...暂停方便看清楚输出结果return 0; // 程序正常退出
}2.5 引用本质
本质 引用的本质在c内部实现是一个指针常量 int * const p
#include iostream // 包含标准输入输出流文件
using namespace std; // 使用标准命名空间// 发现是引用转换为 int* const ref a;
void func(int ref) {ref 100; // ref是引用转换为*ref 100
}int main() {int a 10;// 自动转换为 int* const ref a; 指针常量是指针指向不可改也说明为什么引用不可更改指向a地址后不可再指向b地址int ref a;ref 20; // 内部发现ref是引用自动帮我们转换为: *ref 20解引用cout a: a endl; // 20cout ref: ref endl; // 20cout endl;system(pause); // 相当于在本地 Windows 调试器中的请按任意键继续...暂停方便看清楚输出结果return 0; // 程序正常退出
}结论C推荐用引用技术因为语法方便引用本质是指针常量但是所有的指针操作编译器都帮我们做了 2.6 常量引用
作用 常量引用主要用来修饰形参防止误操作
在函数形参列表中可以加 const修饰形参防止形参改变实参
// 引用使用的场景通常用来修饰形参#include iostream // 包含标准输入输出流文件
using namespace std; // 使用标准命名空间// 打印数据函数
void showValue(const int v) { // const修饰形参形参引用//v 10; // 加const后v的值不可修改会提示错误cout v endl;
}int main() {//int ref 10; // 引用本身需要一个合法的内存空间栈区、堆区数据因此这行错误10是常量在常量区// 加入const就可以了编译器优化代码int temp 10; const int ref temp;const int ref 10;// ref 100; //加入const后不可以修改变量变为只读cout ref endl; // 10// 函数中利用常量引用防止误操作修改实参int a 10; // 如果函数showValue()未加const在函数内修改v会将a的值也进行修改showValue(a); // 10cout endl;system(pause); // 相当于在本地 Windows 调试器中的请按任意键继续...暂停方便看清楚输出结果return 0; // 程序正常退出
}总结
1、C 中在程序运行前分为全局区和代码区
2、代码区特点是共享和只读
3、全局区中存放全局变量、静态变量、常量
4、常量区中存放 const 修饰的全局常量和字符串常量
5、堆区数据由程序员管理开辟和释放
6、堆区数据利用new关键字进行开辟内存
7、通过引用参数产生的效果同按地址传递是一样的。引用的语法更清楚简单。