7.5局部对象

在C++语言中,对于每一个变量和对象,都有其各自的作用域和生存期,这两个概念一个是空间的,一个是时间的。对象的作用域指的是该变量的程序文本区,对象的生存期则是程序执行过程中对象存在的时间。

7.5.1自动对象

只有当定义它的函数被调用的时候才存在的对象称为自动对象,自动对象在每次调用函数时创建和销毁。

局部变量所对应的自动对象在函数控制经过变量定义语句时创建。如果在定义时提供了初始化,那么每次创建对象时,对象都会被初始化为指定的初值。对于未初始化的内置类型局部变量,其初值是不确定的随机值(当然这里的随机指的是伪随机)。当函数调用结束时,自动对象就会被撤销。

7.5.2 静态局部对象

一个变量如果位于函数的作用域内,但生存期却跨越了这个函数的多次调用,这种变量往往很有用,则应该讲这样的对象定义为static。

static局部对象确保不迟于在程序执行流程第一次经过该对象的定义语句时进行初始化。这种对象一旦被创建,在程序结束前都不会被撤销。看下面的这个例子,这个函数计算了自己被调用的次数:

#include <iostream>
using namespace std; size_t count_calls()
{
static size_t ctr = 0;
return ++ctr;
} int main()
{
for(int i = 0; i < 10; i++)
{
cout << count_calls() << endl;
} return 0;
}

  程序执行结果:这个程序一次输出1到10(包括10)的整数。

问题与解决

第一次读到上面的程序的时候,有一点疑问:上面的那句话static size_t ctr = 0会不会在每次调用函数的时候把ctr弄成0呢?

当然答案是不会的,不然这个static不就等于不写了吗?

这里还是要搞清楚一个概念,那就是变量的初始化和赋值两种不同的操作。任何变量的初始化都只有一次,就是在变量定义的时候,也就是内存刚刚分配之后的瞬间;赋值操作是修改变量内原来的值(里面的值可能是初始化得到的,也可能是上次赋值得到的)。

静态全局变量就是在main函数调用之前调用的。
静态局部变量则在第一次使用之前调用的。

静态变量的初始化是在首次执行到初始化语句时间执行的,编译时在初始化语句之前放置一个标志位,每次进行判断,倘若需要初始化则执行初始化操作,否则不执行。上面的那句static size_t ctr = 0就是静态局部变量的初始化,只是在第一次调用这个函数,初始化这个静态对象的时候才会被执行,后面的其他次的调用该函数是不会执行这句话的。

那么为什么普通局部变量在每次函数调用的时候都要执行size_t ctr = 0这句话呢?(假设这个函数中有这么一句话)因为它是普通的局部变量,上次的已经被销毁了,这次是重新开辟的内存空间,要对新的内存空间也就是对象进行初始化。而静态局部对象在上次调用之后没有被销毁,所以这次调用不会分配内存空间,当然不用执行初始化的语句了。

实例展示

下面的四个函数,不同的地方仅仅差别在于定义的变量的属性(是不是static)和有没有初始化。

static int ctr = 0仅仅起的是一个初始化的作用,在若干次执行test1()函数时,static int ctr = 0;只在第一次test1()函数被调用的时候初始化为0,当test1()第二次或更多次被调用时,ctr为保存的上一次的值。

#include <iostream>

using namespace std;

void test1(void)
{
static int ctr = 0; //静态变量,初始化为0
cout << "ctr1_1:" << ctr << endl; ++ctr;
cout << "ctr1_2:" << ctr << endl; } void test2(void)
{
int ctr = 0; //非静态变量,初始化为0
cout << "ctr2_1:" << ctr << endl; ++ctr;
cout << "ctr2_2:" << ctr << endl;
} void test3(void)
{
static int ctr; //静态变量,未初始化
cout << "ctr3_1:" << ctr << endl; ++ctr;
cout << "ctr3_2:" << ctr << endl;
} void test4(void)
{
int ctr; //非静态变量,未初始化
cout << "ctr4_1:" << ctr << endl; ++ctr;
cout << "ctr4_2:" << ctr << endl;
} int main()
{
for(int i = 0; i < 4; i++)
{
test1();
test2();
test3();
test4();
cout << "--------------" << endl;
} return 0;
}

  程序执行结果:

C++静态局部对象的更多相关文章

  1. C++静态变量对象的建立和删除,兼论MFC开始运行的起点(全局对象)

    看了不少C++书,当讲到静态变量的时候,总是以int成员来举例,是啊,这样很好理解.但是如果这个静态变量是一个对象行不行呢?不仅行,有时候还非常必要,而且别有洞天. 比如: // .h 文件 clas ...

  2. 关于C++函数返回局部对象的详细分析

    以前一直挺好奇的,C++是怎么在函数内返回一个局部对象的.因为按照我之前的想法,函数返回一个基本类型的值是通过存放到ecx实现的(关于浮点不了解),但是局部对象又是比较大的,很明显不能使用寄存器作为通 ...

  3. “全栈2019”Java第九十五章:方法中可以定义静态局部内部类吗?

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  4. c/c++不能返回局部对象和局部变量的指针或引用解释

    在编写c/c++代码时,调用函数的书写让程序变得整洁易读,但是调用函数的返回值(局部变量的返回值,变量,结构体,数组等)也有注意事项.c/c++严禁返回局部变量的指针或引用. 其实函数的返回值的规则非 ...

  5. 条款31: 千万不要返回局部对象的引用,也不要返回函数内部用new初始化的指针的引用

    先看第一种情况:返回一个局部对象的引用.它的问题在于,局部对象 ----- 顾名思义 ---- 仅仅是局部的.也就是说,局部对象是在被定义时创建,在离开生命空间时被销毁的.所谓生命空间,是指它们所在的 ...

  6. C++ //拷贝构造函数调用时机//1.使用一个已经创建完毕的对象来初始化一个新对象 //2.值传递的方式给函数参数传值 //3.值方式返回局部对象

    1 //拷贝构造函数调用时机 2 3 4 #include <iostream> 5 using namespace std; 6 7 //1.使用一个已经创建完毕的对象来初始化一个新对象 ...

  7. jquery源码解析:jQuery静态属性对象support详解

    jQuery.support是用功能检测的方法来检测浏览器是否支持某些功能.针对jQuery内部使用. 我们先来看一些源码: jQuery.support = (function( support ) ...

  8. PHP 简单面向对象 验证码类(静态实例对象调用)

    没事写了一个简单的面向对象验证码类,可以直接使用(替换一下字体路径) <?php class authCode { private static $instance = null; #实例对象 ...

  9. C++ 静态对象

    一:什么是静态对象?     对象的存储方式是静态的.        局部静态对象和类的静态对象.      局部静态对象:一个变量在函数内部定义,其生命周期跨越了该函数的多次调用.局部对象确保不迟于 ...

随机推荐

  1. centos扩容(pv,vg,lv)

    preFace: (应用场景需求分析)

  2. error while loading shared libraries: libevent-1.x.so.1

    安装完memcache后启动报错(error while loading shared libraries: libevent-1.x.so.1) 这是由于64位linux会去/usr/lib64目录 ...

  3. Android ROM 制作教程

    本文来自: 起点手机论坛 具体文章參考:http://www.qdppc.com/forum.php?mod=viewthread&tid=43751&fromuid=1 1.Andr ...

  4. 智能家居项目(2):项目project框架的搭建

    项目管理器: Linux中的项目管理器"make"有些类似于windows中的Visual C++里的"project",它是一种控制编译或者反复编译软件的工具 ...

  5. CSS3 旋转3D立方体

    <meta charset="utf-8"> <style> *{ margin:0px; padding:0px; } @-webkit-keyframe ...

  6. KVC中setValuesForKeysWithDictionary:

    本文转载于:http://my.oschina.net/u/2407613/blog/524879?p={{page}} 从字典映射到一个对象,这是KVC中的一个方法所提供的,这个方法就是 setVa ...

  7. 创建oracle数据库的表空间、用户、目录、导入\导出文件等信息

    1.创建表空间 create tablespace ts_aw logging datafile 'd:\app\Administrator\product\tablespace\ts_aw.dbf' ...

  8. 前端页面优化:javascript图片延迟加载

    自己写了个简单的图片延迟加载小插件. 功能如下: 页面刷新,当前屏幕图片直接加载真实地址,body被卷去的部分和下方未显示的部分的img均加载通用图片如:loding.gif 随着屏幕上下滚动加载相应 ...

  9. CSS3里面的高级属性

    -webkit-tap-highlight-color 这个属性只用于iOS (iPhone和iPad).当你点击一个链接或者通过Javascript定义的可点击元素的时候,它就会出现一个半透明的灰色 ...

  10. symfony2-创建提交表单生成数据过程

    一.”一对多“关系 表shop(一)