局部变量及其生命周期详解

内存机制

在谈变量之前首先需要了解一下c++的内存机制:
在这里插入图片描述即:
在这里插入图片描述在这里插入图片描述进一步可以通过思维导图更加清晰的理解与记忆:
在这里插入图片描述

变量及其生命周期

局部变量:在函数内部或复合语句内部定义的变量,在其作用域内有效(作用域{});
即:在一个函数内部定义的变量只在本函数范围内有效,也就是说只有在本函数内才能引用它们,在此函数外是不能使用这些变量的。在复合语句内定义的变量只在本复合语句范围内有效,只有在本复合语句内才能引用它们;

#include<iostream>
using namespace std;
int add(int &m, int &n);
int main()
{
	int a = 2, b = 3,c=0;
	while (true)
	{
		int c;
		int a = 4, b = 5;
		c = add(a, b);
		cout << "a+b=" << c << endl;
		break;
	}
	c=add(a,b);
	cout << "a+b=" << c<<endl;
	return 0;
}
int add(int &m, int &n)
{
	return m + n;
	//return m+n+c;此句话的目的验证(1);
}

a+b=9
a+b=5
请按任意键继续. . .
这个结果显然易见,但是本次实验最重要的目的在于:
(1).a=2,b=3,c=0的作用范围是整个main函数(从“{”到“}”),哪add()函数也在这个范围内,哪么在add()函数范围内,.a=2,b=3,c=0还成立吗?答案是否定的。
这是由于函数调用的规则决定,执行add()函数,程序会自动跳转到add()函数范围内,这个范围内超出了a,b,c的作用域,所以无效。
既然如此,如果将add()函数定义成
内联函数
,此时a,b,c是否有效?然而结果是否定的

#include<iostream>
using namespace std;
inline int add(int &m, int &n);
int main()
{
	int a = 2, b = 3,c=0;
	while (true)
	{
		int c=0;
		int a = 4, b = 5;
		c = add(a, b);
		cout << "a+b=" << c << endl;
		break;
	}
	c=add(a,b);
	cout << "a+b=" << c<<endl;
	return 0;
}
 inline int add(int &m, int &n)
{
	return m + n+c;
}

结论:

1.主函数中定义的变量(如a,b,c)也只有在主函数中有效,并不因为在主函数中定义而在整个文件或程序中有效。主函数也不能使用其他函数中定义的变量;
2.不同函数中可以使用同名的变量,他们代表不同的对象,互补干扰。
3.形参也是局部变量;
4.在一个函数内部,可以在复合语句中定义变量,这些变量只在本复合语句中有效;

全局变量:在函数外部定义,作用范围从定义位置到程序结束;

动态存储方式与静态存储方式:

有上面可以知道,从变量的作用域(即从空间)的角度来观察,变量可以分成全局变量局部变量
本节从另一个角度,即从变量值存在的时间(即生存期)来观察。有的变量在程序运行的整个过程都是存在,**而有的变量则是在调用其所在的函数时,才临时分配存储单元,而在函数调用结束后该单元就马上释放了,变量不存在了。**也就是说变量的存储有两种方式:
静态存储方式:指在程序运行期间由系统分配固定存储空间的方式。
动态存储方式:在程序运行期间根据需要进行动态的分配存储空间;
由内存分配机制中可以看出,内存被分成三块区域,数据分别存储在
静态存储区与动态存储区
中;
在这里插入图片描述

静态存储区的特点:

在程序开始执行时分配存储空间,程序执行完毕后释放。在程序执行过程中,他们占据固定的存储单元,而不是动态地进行分配和释放;

动态存储区的特点:

在函数调用时分配存储空间,函数调用结束时就释放这些空间。在程序执行过程中,这种分配和释放是动态的,如果在一个程序中,两次调用同一函数,而在此函数中定义的局部变量,在两次调用时分配这些局部变量存储空间的地址可能是不相同的。
一次调用结束后其内存释放,下一次调用时重新分配内存;

完整的变量

一个完整的变量具有两种属性:数据类型数据的存储类别
数据类型如:整型、浮点型;
数据的存储类别:自动的(auto)、静态的(static)、寄存器的(register)、外部的(extern)

局部变量的存储类别

  1. 自动变量(auto):函数中的局部变量,如果不专门声明为static(静态)存储类别,都是动态地分配存储空间的,数据存储在动态存储区中。如函数的形参和函数中定义的局部变量(包括在复合语句中定义的局部变量)。在调用该函数时,系统会给这些变量分配存储空间,在函数调用结束时就自动释放这些存储空间。因此,这类局部变量称为自动变量。
  2. **静态变量(static):有时候,希望函数中的局部变量的值在函数调用结束时不消失而继续保留原值,即其占用的存储单元不释放,在下一次再调用该函数时,该变量已有值(就是上一次函数调用结束时的值)。**这时就应该指定该变量为静态局部变量,用关键字“static”进行声明;
#include<iostream>
using namespace std;
int main()
{
	int display(int);
	int a = 2, i;
	for ( i = 0;i < 3; i++)
	{
		cout << display(a) << endl;
	}
	return 0;
}
int display(int a)
{
	int b = 0;		//自动局部变量
	static int c = 3;//静态局部变量
	b = b+1;
	c = c + 1;
	return a + b + c;
}

结果:7、8、9;
在这里插入图片描述注意:
1.静态局部变量属于静态存储类别,在静态存储区内分配存储单元。在程序整个运行期间都不释放
2.自动变量属于动态存储类别,分配在动态存储区域空间而不在静态存储区空间,函数调用结束后即释放
3.对静态局部变量是在编译时赋初值,即只赋初值一次,在程序运行时它已有初值。以后每次调用函数不在重新赋初值,而只是保留上次调用结束的值。
4.而对自动变量赋初值,不是在编译时候进行的,而是在函数调用时进行的,每调用一次函数重新给一次初值,相当于执行一次赋值语句;
这是由于,静态局部变量在程序运行的整个过程都会存在,在编译时赋值一次后,其局部静态变量的值将是一个确定的值(随程序执行可能改变,但是确定的,可控的),下一次调用时,其存储空间的值是上一次调用结束后的值。而自动变量,是在程序调用时才分配存储空间,所以其存储空间的初始值是未知的,是不可控的,为了安全起见,调用一次,初始化一次。
5.如果在定义局部变量不赋初值,则对静态局部变量来说,编译器会自动赋值0(数值类型变量)或‘\0’(字符型变量)。**而对于自动变量,他的值是一个不确定的值。**至于原因大家应该已经知道了,即由于每次函数调用结束后存储单元已经释放,下次调用时又重新分配存储单元,而所分配的单元中的内容是不可知的。
6.虽然静态局部变量在函数调用结束后仍然存在,但是其他函数是不能引用他的。因为他是局部变量,只能被本函数引用(只在其作用域内有效),而不能被其他函数引用;
3. 寄存器变量:几乎不用;

参考资料:《C程序设计<第四版>》谭浩强 著.北京:清华大学出版社。
图片来源:知乎,不知道先生;

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值