详解C++中的自动存储

 更新时间:2020年09月27日 10:33:13   作者:chuyaoxin  
这篇文章主要介绍了详解C++中的自动存储,帮助大家更好的理解和学习C++,感兴趣的朋友可以了解下

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

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

自动存储(栈存储)

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

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

代码段1

int add(int m,int n)

{

  //z的生存期包括整个函数

  int z=m+n;

  return z;

}

代码段2

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被撤销,对应内存被释放。

void demo()

{

  ……

  auto int A;

  ……

}

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

3.register关键字

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

提示

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

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

register int sum=9;

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

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

void demo()

{

  ……

  register int sum=0;

  int*pSum=∑

  ……

}

注意

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

4.自动变量的初始化

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

n=2;

n=5*m;//m的值确定

n=add(4,6);

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

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

相关文章

  • C语言可变参数函数详解

    C语言可变参数函数详解

    在某些情况下我们希望函数的参数个数可以根据需要确定,因此c语言引入可变参数函数。典型的可变参数函数的例子有printf()、scanf()等,下面我就开始讲解
    2021-08-08
  • C++ vector模拟实现的代码详解

    C++ vector模拟实现的代码详解

    vector是表示可变大小数组的序列容器,就像数组一样,vector也采用的连续存储空间来存储元素,本质讲,vector使用动态分配数组来存储它的元素,本文将给大家详细介绍一下C++ vector模拟实现,需要的朋友可以参考下
    2023-07-07
  • Qt读取和写入配置(ini)文件

    Qt读取和写入配置(ini)文件

    ini文件在windows系统中可以存储需要持久保存的配置信息,本文主要介绍了Qt读取和写入配置(ini)文件,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09
  • MoveWindow() SetWindowPos()的区别于联系

    MoveWindow() SetWindowPos()的区别于联系

    这篇文章主要介绍了VC++中MoveWindow() SetWindowPos()的区别于联系,需要的朋友可以参考下
    2015-01-01
  • 深入浅析C/C++语言结构体指针的使用注意事项

    深入浅析C/C++语言结构体指针的使用注意事项

    这篇文章主要介绍了C/C++语言结构体指针的使用,大家都知道指针在32位系统占用4Byte,在64位系统占用8Byte,下面看下c语言代码例子
    2021-12-12
  • C语言中sizeof函数踩过的坑总结

    C语言中sizeof函数踩过的坑总结

    sizeof是C语言的一种单目操作符,如C语言的其他操作符++、--等。它并不是函数。sizeof操作符以字节形式给出了其操作数的存储大小。操作数可以是一个表达式或括在括号内的类型名。操作数的存储大小由操作数的类型决定
    2022-04-04
  • Cocos2d-x学习笔记之开发环境搭建

    Cocos2d-x学习笔记之开发环境搭建

    这篇文章主要介绍了Cocos2d-x学习笔记之开发环境搭建,本文使用Visual Studio作为开发IDE,是不同于其它教程的,需要的朋友可以参考下
    2014-09-09
  • C语言超详细讲解文件的操作

    C语言超详细讲解文件的操作

    C语言文件操作的方法有很多,函数也有很多你知道哪些呢?下面是小编为大家带来的C语言文件操作的方法,欢迎阅读
    2022-04-04
  • C++计算任意两个日期天数差的方法详解

    C++计算任意两个日期天数差的方法详解

    这篇文章主要为大家详细介绍了如何利用C++实现任意两个日期天数差,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下
    2024-02-02
  • 使用C++将处理后的信号保存为PNG和TIFF格式

    使用C++将处理后的信号保存为PNG和TIFF格式

    在信号处理领域,我们常常需要将处理结果以图像的形式保存下来,方便后续分析和展示,C++提供了多种库来处理图像数据,本文将介绍如何使用stb_image_write库保存为PNG格式图像以及使用OpenCV库保存为TIFF格式图像,需要的朋友可以参考下
    2025-02-02

最新评论