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. Android切换页面效果的实现一:WebView+ViewFlipper

    前言: 这两周在帮学校做一个新生入学用的“新里程”的项目,要做到页面切换阅读的效果,自己百度了下,找到普遍是使用WebView+ViewFlipper的实现方法,但这种方法不能满足我的要求,因为它很难 ...

  2. javascript关键字加亮加连接

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" " http://www.w3.org/TR/html4/str ...

  3. [置顶] 北漂的大三IT男(暂完)

    今天是2013年8月9日,是我待在北京的最后一个晚上,今天我已经正式向公司提出辞职了,虽然公司已经答应从下个月起涨部分工资,但是我还是坚决的离开了,回想当时进公司的想法----------干了一个月后 ...

  4. WebConfig特殊字符的转义!

    Web.Config默认编码格式为UTF-8,对于XML文件,要用到实体转义码来替换.对应关系如下: 字符 转义码 & 符号 & & 单引号 ' &apos; 双引号 ...

  5. BootStrap 模态框禁用空白处点击关闭问题

    模态框为信息编辑窗口,涉及好多内容,填了半天,若一不小心点了空白处,那就前功尽弃了..... 所以我们很有必要禁用鼠标点击空白处模态框关闭的功能. $('#myModal').modal({backd ...

  6. APP应用的发展趋势

    PhoneGap 是什么 PhoneGap 是一个用基于HTML,CSS 和JavaScript 的,创建移动跨平台移动应用程序的快速开发框架.它使开发者能够利用iPhone,Android,Palm ...

  7. android webview点击返回键回到上一个html

    android webview点击返回键返回上一个html @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if ( ...

  8. 在win7下装ubuntu(硬盘版安装)及遇到的问题

    都怪自己弄什么Ubuntu下的Android Studio,因为GFW,gradle总下载不了,用命令行下载一半关机了,然后Ubuntu就这样被我搞残废了.又张罗着重装. 其实就是参照网上的帖子,算是 ...

  9. SQL2008 'OFFSET' 附近有语法错误。 在 FETCH 语句中选项 NEXT 的用法无效。

    'OFFSET' 附近有语法错误.在 FETCH 语句中选项 NEXT 的用法无效. 说明: 执行当前 Web 请求期间,出现未经处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出 ...

  10. Java基础之静态变量

    public class StaticVariable { public static void main(String[] args) { Person p1 = new Person(); Per ...