1、C++中变量生存周期
参考:https://blog.csdn.net/darkxiaoming/article/details/70232620
在C++中变量有以下两种生存周期:
- 变量由编译程序在编译时给其分配存储空间(称为静态存储分配),并在程序执行过程中始终存在。这类变量的生存周期与程序的运行周期相同,当程序运行时,该变量的生存周期随即存在,程序运行结束,变量的生存周期随即终止。
- 变量由程序在运行时自动给其分配存储空间(称为自动存储分配),这类变量为函数(或块)中定义的自动变量。它们在程序执行到该函数(或块)时被创建,在函数(或块)执行结束时释放所占用的空间。
注:在C++中,当标识符的作用域发生重叠时,在一个函数(或块)中声明的标识符可以屏蔽函数(或块)外声明的标识符或全局标识符。
>变量作用域示例:
#include<iostream>
using namespace std;
int i=0; //line 0
int main()
{
int i=1; //line 1
cout<<"i="<<i; //line 2
{ //line 3
int i=2; //line 4
cout<<"i="<<i; //line 5
{ //line 6
i+=1; //line 7
cout<<"i="<<i; //line 8
} //line 9
cout<<"i="<<i; //line 10
} //line 11
cout<<"i="<<i<<endl; //line 12
system("pause");
return 0; //line 13
}
>程序运行结果:
>分析:
在函数外面定义的全局变量i(0行),它的作用域应为整个程序。在main函数开头处定义的局部变量i(1行),它的作用域为整个函数,即从1行到13行,根据上面标识符作用域冲突规定,在2行的输出语句将输出定义在1行的变量i的值,即为1。在4行定义的局部变量i,其作用域为所在块,即从4到10行,同样根据标识符作用域冲突规定,在5行的输出语句将输出定义在4行的变量i的值,即为2;同时由于7行所操作的变量i正处于定义在4行的变量i的作用范围内,因此将其值加1,得i=3,所以8行的输出语句输出变量i的值为3。同理,由于10行所输出的变量i正处于定义在4行变量i的作用域范围内,因此输出结果为3(其值在7行修改)。而在12行的输出语句所输出的变量i处于定义在1行变量i的左右范围内,因此输出结果为1(其值未被修改过)。
由于作用域的屏蔽效应,如果函数中有同名变量,则不能访问外部变量。
为了能在函数内部访问函数外部定义的变量,可以使用C++中的作用域运算符“ :: ”。通过作用域运算符,即使该函数(或块)中已有与之同名的变量,也可以在函数(块)中使用定义在函数(块)外的全局变量。此外作用域运算符还可以用来指定类成员变量或成员函数所属的类。
当程序较大时,利用名字屏蔽机制是非常必要的。但是,这也会导致程序的可读性变差,好的程序设计风格应尽量避免名字屏蔽。
2、python 中变量生存周期
参考:https://blog.csdn.net/u012965373/article/details/53113586
https://blog.csdn.net/weixin_35640856/article/details/73614294
最近在写Python的时候发现一个好玩的现象,就是在if else重定义的变量,没有声明全局,在外部也可以使用,
这里涉及到一个python变量生命周期的问题。
python能够改变变量作用域的代码段是def、class、lamda.
if/elif/else、try/except/finally、for/while 并不能涉及变量作用域的更改,
也就是说他们的代码块中的变量,在外部也是可以访问的
变量搜索路径是:本地变量->全局变量
python中,对于变量作用域的规定有些不一样。在诸如C/C++、java等编程语言中,默认在函数的内部是可以直接访问在函数外定义的全局变量的,但是这一点在python中就会有问题,下面是一个例子。
test.py:
#!/usr/bin/python
COUNT=1
def func():
COUNT = COUNT + +1
func()
Python test.py,会运行报错:
Traceback (most recent call last):
File "test.py", line 8, in
func()
File "test.py", line 6, in func
COUNT = COUNT + +1
UnboundLocalError: local variable 'COUNT' referenced before assignment
“UnboundLocalError: local variable 'COUNT' referenced before assignment”的意思是变量COUNT在赋值之前被引用。
这里要知道python和其它编程语言不一样的地方。像C/C++之类的编程语言,变量名称实际上是代表的一块内存区域,对该变量赋值的意思就是将新的值放入该变量指定的内存区域。而对于python来说,所有的变量都是对内存区域的引用,对变量赋值相当于将变量引用的内存从一块区域改变到另外一块存放新值的区域。也就是说,C/C++中,变量名和内存区域的对应关系不会变,变的只是对应内存中存放的值;而在python中,变量只是对存放其值的内存区域的引用,变量值的改变不是因为变量指向的内存区域中的值发生了变化,而是变量引用了新的存放新值的内存区域。python中的所有变量都是相当于java中的不可变的变量,任何一次值的改变都对应着变量引用内存区域的变化。区别如下图1:
python中有一个id函数,id函数反应的是对象的内存地址,看下面的实验结果:
test.py:
#!/usr/bin/python
COUNT = 1
for i in range(5):
COUNT = COUNT + 1
print id(COUNT)
python test.py运行结果:
11031328
11031304
11031280
11031256
11031232
这里和上面图上说明的相吻合,python中每一次赋值都使变量引用的内存空间发生了改变。
回到上面“referenced before assignment”的错误,之所以会发生这种错误是因为python在函数中发现对于COUNT变量的赋值,会将其添加到函数的局部命名空间(实际上,这是在函数运行到赋值操作之前发生的)。进行赋值操作时,赋值操作符的右边引用了COUNT变量,而这时COUNT变量只是被添加到了函数的局部命名空间,而没有被具体赋值,所以会发生上面的错误。实际上,这里问题就出在赋值操作的地方,因为有赋值操作导致该变量被添加到了函数的局部命名空间。如果没有赋值,只是引用该变量,是没有什么问题的,如下:
test.py:
#!/usr/bin/python
COUNT=1
def func():
temp = COUNT + 1
print "temp:",temp
print "COUNT:",COUNT
func()
python test.py运行结果:
temp: 2
COUNT: 1
这样,COUNT变量没有被添加到函数的局部命名空间,python解释器在函数的局部命名空间中没有查找到它,然后,python解释器会继续在全局的命名空间中查找,结果在全局命名空间中找到COUNT的定义并引用它的值,所以程序运行没有任何问题。
到这里你可能会问,难道在函数中没法修改全局变量的值吗?不是的,如果要在函数中修改全局变量的值,就要在函数中对该变量进行global声明,以告诉python解释器,该变量是全局命名空间中的,如下:
test.py:
#!/usr/bin/python
COUNT=1
def func():
global COUNT
COUNT = COUNT + 1
print "COUNT:",COUNT
func()
python test.py运行结果:
COUNT: 2