1、c++内存模型
c++程序执行时将内存大致分为4个区域
- 代码区:存放CPU执行的二进制代码指令,由操作系统进行管理
- 全局区:存放全局变量和静态变量以及全局常量和字符串常量
- 栈区:由编译器自动编译释放,存放函数的参数值,局部变量等
- 堆区:由程序员分配释放,如果程序员不释放,则程序结束时由操作系统回收
c++内存模型图如下:
代码区特点
共享的:对于频繁执行的程序,在内存中只要有一份代码即可
只读的:防止系统意外修改它的指令
全局区特点
该区域的数据,在程序结束后由操作系统释放
栈区特点
由编译器自动编译释放,存放函数的参数值,局部变量等
注意事项:栈区编译的数据执行完后由编译器自动释放,不要返回局部变量的地址
堆区特点
由程序员分配释放,若程序员不释放,程序结束时由操作系统回收
在c++中主要通过new关键字在堆区开辟内存
new 和delete关键字
new关键字开辟内存
elete关键字释放指针p指向的内存
int* func()
{
//用new关键字开辟内存,new返回的是该数据的指针
int * p = new int(21);
return p;
}
int main()
{
int * p = func();
cout << *p << endl;
//使用delete关键字释放指针p指向的内存
delete p;
system("pause");
return 0;
}
2、引用
引用可以看做是变量的一个别名,通过这个别名和原来的名字都能够找到这个变量。
语法:
//数据类型 &别名 = 原名
int a = 10;
int &b = a;
注意事项:引用必须在定义的同时初始化,并且以后也要从一而终,不能再引用其它变量。
引用作为函数参数
将函数的形参指定为引用的形式,这样在调用函数时就会将实参和形参绑定在一起,让它们都指代同一个变量。如此一来,如果在函数体中修改了形参的值,那么实参的值也会被修改。
//引用传递,&a1,&b1分别是变量a和b的引用
void swap(int &a1,int &b1)
{
int temp = a1;
a1 = b1;
b1 = temp;
}
int main()
{
int a = 10;
int b = 20;
swap(a, b);
cout << a << "\n" << b << endl;
system("pause");
return 0;
}
引用作为函数返回值
不能返回局部数据(例如局部变量、局部对象、局部数组等)的引用,因为当函数调用完成后局部数据就会被销毁,有可能在下次使用时数据就不存在了,C++ 编译器检测到该行为时也会给出警告。
int& test() {
static int a = 10;//这里把a变成静态变量,存放在全局区,全局区的数据在程序结束后由系统释放
return a;
}
int main()
{
int &ref = test();
cout << ref << endl; //10
test() = 1000;//如果函数的返回值是引用,这个函数调用可以作为左值
cout << ref << endl; //1000
system("pause");
return 0;
}
引用的本质
引用的本质是一个指针常量,所有指针操作由编译器完成。
常量引用
常量引用主要用来修饰形参,防止误操作;
在函数中可以用const修饰形参,防止形参改变实参
void showValue(const int& a1) {
// a1+=1000; 不允许修改
cout << a1 << endl;
}
int main()
{
int a = 10;
showValue(a);
system("pause");
return 0;
}
3、函数高级
函数默认参数
在c++中函数的形参列表中的参数是可以有默认值的;
在函数中如果某个参数有默认值,那么它后面的所有参数都得有默认参数;
如果函数声明有默认参数,那么函数的定义就不能有默认参数
//如果我们有传入数据,就用传入的数据,没有的话就用默认数据
int func01(int a, int b = 10, int c = 10) {
return a + b + c;
}
//函数声明,存在默认参数
int func02(int a, int b = 10);
//那么在函数定义时就不能有默认参数
int func02(int a, int b) {
return a + b;
}
int main()
{
cout << func01(1, 4) << endl;//15
cout << func01(1) << endl; //21
cout << func02(1) << endl; //11
system("pause");
return 0;
}
函数占位参数
c++中函数的形参列表可以有占位参数,用来占位,调用函数时必须填补该位置
占位参数还可以有默认值
//占位参数,设置了默认值
void func(int a, int = 5) {
cout << "This is a function " << endl;
cout << a << endl;
}
int main() {
//调用函数时填补占位参数
func(12, 9);
system("pause");
return 0;
}
函数重载
重载:函数名称相同,函数参数类型不同或者个数不同或者顺序不同
void func() {
cout << "This is a function 01 " << endl;
}
void func(int a) {
cout << "This is a function 02" << endl;
}
void func(double a) {
cout << "This is a function 03" << endl;
}
void func(int a,double b) {
cout << "This is a function 04" << endl;
}
void func(double a, int b) {
cout << "This is a function 05" << endl;
}
注意事项:
- 引用可以作为重载条件
- 重载时避免出现默认参数,会出现二义性