c++内存模型和引用

39 阅读2分钟

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;
}