服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - 详解C++中的自动存储

详解C++中的自动存储

2021-09-28 10:54chuyaoxin C/C++

这篇文章主要介绍了详解C++中的自动存储,帮助大家更好的理解和学习C++,感兴趣的朋友可以了解下

C++有3种管理数据内存的方式即自动存储(栈存储)、静态存储和动态存储(堆存储)。在不同的方式下,内存的分配形式和存在时间的长短都不同。

下面对自动存储进行说明。

自动存储(栈存储)

对于函数的形参、内部声明的变量及结构变量等,编译器将在函数执行时为形参自动分配存储空间,在执行到变量和结构变量等的声明语句时为其自动分配存储空间,因此称其为自动变量(Automatic Variable),有的教科书也称其为局部变量,在函数执行完毕返回时,这些变量将被撤销,对应的内存空间将被释放。

事实上,自动变量的生存期只局限于它所在的代码块。所谓代码块,是包含在花括号对中的一段代码,函数只是代码块的一种,比较下面两段代码。

代码段1

?
1
2
3
4
5
6
7
8
9
10
11
int add(int m,int n)
 
{
 
  //z的生存期包括整个函数
 
  int z=m+n;
 
  return z;
 
}

代码段2

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int add(int m,int n)
 
{
 
  if(m!=0)
 
  {
 
    //z的生存期包括在这个代码块中
 
    int z=m+n;
 
  }
 
  return z;//错误
 
}

在代码段1中,当函数返回时,变量z被撤销,对应内存空间被释放,但在代码段2中,在if代码块中声明的变量z,其生存期仅限于if结构的两个花括号之间,当程序执行到if结构的后花括号时,变量z已被撤销,其对应的内存空间被释放,此时,再执行“return z;”语句便会出错。

注意

理解代码块的含义十分重要,花括号不是判断代码块的唯一标准,把代码段2中if结构的花括号去掉,代码仍然是错误的,将“return z;”放在if结构中是正确的用法。

自动变量的生存期是局部的,这一特性使得程序员可以在不同的块内使用相同的变量名,用不着为使用不同的变量名绞尽脑汁。

1.什么是“栈”

栈(Stack)是一块存储区,而且是C++程序使用最频繁的存储区,其存储机理为“FILO”,即先进后出(First In,Last Out)。可以将其想象成一个装盘子的桶,最早放入的盘子在桶的底部,最晚放入的盘子在最顶部,取盘子时必须先从后放进去的盘子开始取,这就是所谓的先进后出原则。当一个代码块(包括函数,视为一种特殊的代码块)声明一个自动变量时,系统便为其在栈中开辟内存空间(常称“压入”push),该代码块结束后便将自动变量撤销,释放内存空间(常称“弹出”pop)。

注意

采用“栈”这种机制,C++程序能有效地节省所用内存空间。

2.auto关键字

auto是C++提供的存储类声明符,用于声明自动变量,除了auto声明符外,C++还提供了另外3个存储类声明符,分别是register(寄存器存储)、extern(外部存储)和static(静态存储)。在声明创建变量时,存储类声明符应放在数据类型声明符之前,如下所示。

存储类声明符 数据类型 变量名[=初始化表达式]

其中,初始化表达式是可选的,如下列代码声明创建了int型自动变量A,其只在函数demo()执行期间存在,demo()函数执行完毕后,变量A被撤销,对应内存被释放。

?
1
2
3
4
5
6
7
8
9
10
11
void demo()
 
{
 
  ……
 
  auto int A;
 
  ……
 
}

在前面给出的示例代码在声明自动变量时并没有加auto修饰符,实际上,auto常常可以默认,凡是在函数内部(不论是main()函数还是其他函数)的,没有用其他显式的存储类型声明符,编译器都认为是auto型自动变量。

3.register关键字

除了auto外,还可以通过存储类声明符register来声明自动变量,与auto唯一的不同在于:关键字register通知编译器,用户希望通过CPU寄存器,而不是“栈”来处理某个变量,从而可以在一定程度上加快该变量的访问速度。

提示

一般来说,CPU对寄存器的访问要快过对内存的访问。

用register声明的变量常称为寄存器变量,举例来说,下列代码声明了int型寄存器变量sum,并将其初始化为9,如下所示。

?
1
register int sum=9;

需要注意的是,即使用register声明了某个变量,编译器也不一定会满足它的要求。因为,CPU寄存器可能被占用或者无法存储指定类型的数据等,而且,现在的编译器一般可以自动决定应把哪些变量放在CPU寄存器中,因此,在C++程序中,register关键字很少使用。

使用register关键字会带来一定的负面效果,不管是否能满足要求,编译器认为register型自动变量是存储在CPU寄存器中的,而寄存器是没有内存地址的,所以,不能对register型自动变量进行取地址操作,下列代码是错误的。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
void demo()
 
{
 
  ……
 
  register int sum=0;
 
  int*pSum=∑
 
  ……
 
}

注意

事实上,用auto和register声明的变量除了存储位置不同(一个是“栈”,而另一个可能是“栈”也可能是CPU寄存器)外,并无其他差异,我们可以将其统称为自动变量来考虑。

4.自动变量的初始化

可以在声明自动变量时对其进行初始化,也可以使用任何具有确定值的表达式为自动变量赋值,下列语句都是合法的(假定n为int型自动变量)。

?
1
2
3
4
5
n=2;
 
n=5*m;//m的值确定
 
n=add(4,6);

需要特别注意的是,如果没有在自动变量声明的同时对其初始化,其初始值是随机、不可预料的,为避免随机的初始值给程序带来麻烦,推荐在声明自动变量的同时对其显式初始化。

以上就是详解C++中的自动存储的详细内容,更多关于C++ 自动存储的资料请关注服务器之家其它相关文章!

原文链接:https://www.cnblogs.com/cyx-b/p/12489555.html

延伸 · 阅读

精彩推荐