内存分区模型
c++程序在执行时,将内存大方向划分为4个区域
代码区:存放函数体的二进制代码,由操作系统进行管理的
存放CPU执行的机器指令
共享的,频繁的执行,只需要在内存中存放一份即可
只读的
全局区:存放全局变量和静态变量及常量
全局变量和静态变量存放在此
全局区还包含了常量去,字符串常量和其它常量也存放在此
该区域的数据在程序结束后由操作系统释放
全局区(在全局区中):
全局变量
静态变量 static关键字
常量
字符串常量
const修饰的全局变量(全局常量)
局部变量(不在全局中)
const修饰的局部变量(局部常量)
栈区:由编译器自动分配释放,存放函数的参数值,局部变量等
注意事项:不要返回局部变量的地址,栈区开辟的数据有编译器自动释放
新参数据也会放在栈区
int * func()
{
int a = 10;//局部变量 存放在栈区,栈区的数据在函数执行完后自动释放
return &a;
}
int main()
{
int * p = func();
cout << *p << endl;//第一次可以打印正确的数字,是因为编译器做了保留
cout << *p << endl;//第二次这个数据就不在保留了
system("puase");
return 0;
}
堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收
在c++中主要利用new在堆区开辟内存
//利用new关键字 可以将数据开辟到堆区
//指针 本质也是局部变量 放在栈上,指针保存的数据是放在堆区
在堆区利用new开辟数组
//创建10整形数据的数据,在堆区
int* arr = new int[10];//10代表有10个元素
//堆区的数据 由程序员管理开辟 程序员管理释放
//释放堆区 关键字 delete
delete p;//内存已经被释放,再次访问就是非法操作,会报错
内存四区意义
不同区域存放的数据,赋予不同的生命周期,给我们更大的灵活变成
引用
引用基本语法
数据类型 &别名=原名
引用注意事项
1、引用必须要初始化
int&b;//错误的
2、引用在初始化后,不可以改变
引用做函数的返回值
如果函数的返回值是引用,这个函数的调用可以作为左值
//不要返回局部变量的引用
int& test01()
{
int a = 10;//局部变量存放在四区中的栈区
return a;
}
//返回静态变量引用
int& test02()
{
static int a = 10;//静态变量,存放在全局区,全局区的数据在程序结束后系统释放
return a;
}
int &ref2 = test02();
cout << "ref2=" << ref2 << endl;
cout << "ref2=" << ref2 << endl;
//返回的a的引用,就等于是a=1000
test02() = 1000;//如果函数的返回值是引用,这个函数的调用可以作为左值
cout << "ref2=" << ref2 << endl;
cout << "ref2=" << ref2 << endl;
引用的本质
int a = 10;
//自动转换为int* const ref=&a;指针常量是指针指向不可改,也说明为什么引用不可更改
int& ref = a;
ref = 20;//内部发现ref是引用,自动帮我们转换为:*ref=20;
//结论:C++推荐用引用计数,因为语法方便,引用本质是指针常量,但是所有的指针操作编译器都帮我们做了
常量引用
引用必须引用一块合法的内存空间
加入const之后变为只读,不可以修改
//int a = 10;
//加上const之后 编译器将代码修改 int temp = 10; const int & ref=temp;
//int & ref = 10;//引用必须引用一块合法的内存空间
//const int & ref = 10;
函数中利用常量引用防止误操作修改实参
const使用场景:用来修饰形参,防止误操作
函数的默认参数
//如果我们传入数据,就用默认的,如果没有,就用默认的
//注意事项
//1、如果某个位置已经有了默认参数,那么从这个位置往后,从左到右都必须有默认值
//int func2(int a,int b = 10, int c)
//{
//
//}
//2、如果函数声明有默认参数,函数实现就不能有默认参数
//声明和实现智只有一个默认参数
函数重载
可以让函数名相同,提高复用性
//满足条件
//同一个作用域下
//函数名相同
//函数参数类型不同或者个数不同或者顺序不同
//注意:
函数的返回值不可以作为函数重载的条件
当函数重载碰到默认参数,出现二义性,报错,尽量避免这种情况