C++静态局部对象

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;
}

  程序执行结果:

时间: 2024-10-06 08:01:54

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

自动对象和静态局部对象

1.自动对象默认情况下,局部变量的生命期局限于所在函数的每次执行期间.只有当定义它的函数被调用时才存在的对象称为自动对象.自动对象在每次调用函数时创建和撤销.该类型局部变量存储在栈上,在动态存储区.局部变量所对应的自动对象在函数控制经过变量定义语句时创建.如果在定义时提供了初始化,那么每次创建对象时,对象都会被赋予指定的初值.对于未初始化的内置类型局部变量,其初值不确定.当函数调用时结束,自动对象就会被撤销.形参也是自动对象,其所占存储空间在函数调用时被创建,在函数结束时撤销.2.静态局部对象用

7.4——函数声明,局部对象,内联函数

函数声明: (1)函数在调用之前必须先声明,一个函数可以被声明多次,而只能被调用一次. (2)函数返回值,函数名,函数形参这三个组成函数原型,函数原型描述了函数接口. (3)在头文件中提供函数声明,而在定义函数的的源文件需要包含这个头文件. 局部对象: (1)函数定义的形参和变量的名字只位于函数的作用域中,这些名字只在函数体中可见. (2)自动对象包括函数形参和局部变量,生命周期只存在于函数的执行期间. 静态局部对象(static) (1)若是一个对象位于函数的作用域内,但生命周期存在于函数的多

函数可以返回一个局部对象,而不能返回一个局部对象的引用(指针):

函数可以返回一个局部对象,而不能返回一个局部对象的引用(指针):当函数返回一个局部对象时,虽然这个对象已经释放,但是返回时会产生一个临时的对象.而当返回一个局部对象的引用时,这个对象已经不存在了.这就要求在函数参数中,包含一个引用或指针.int &func(int a,int b,int &retsult){ retsult = a + b; return &retsult}但是如下代码是错误的(返回局部对象的引用)int &func(int a,int b){ int &

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

在编写c/c++代码时,调用函数的书写让程序变得整洁易读,但是调用函数的返回值(局部变量的返回值,变量,结构体,数组等)也有注意事项.c/c++严禁返回局部变量的指针或引用. 其实函数的返回值的规则非常好记: 函数的返回值可以是数值和全局变量的指针或引用. 函数的返回值不能是局部对象或者是局部变量的指针或引用!!! 原因: 调用函数的局部变量是存在于栈中的,在执行完调用函数之后会将局部变量的空间释放,也就是调用函数执行后局部变量将不存在与内存中.如果返回的是局部变量的指针或者是引用.返回给接收对

函数绝对的不要返回指向局部对象指针或引用,该返回对象就返回对象。

首先我们来看一个例子: #include <iostream> using namespace std; const int &fun1(int a,int b) { int i=0; i = a + b; return i; } int main() { if (fun1(1, 2) == fun1(2, 5)) { cout << fun1(1, 2) << endl; cout << fun1(2, 5) << endl; cout

c++返回函数局部对象的引用

    函数千万不要返回局部对象的引用或指针 局部变量在函数里面,当函数执行结束后将释放局部变量,如果返回引用或批针这个时候引用或指针指向所指向的内存空间已经释放.指针和引用将是垂悬指针.很危险! 但是如果返回的"局部变量"是堆中的内存值就可以返回了 C++函数为什么要使用引用? C语言之中大量利用指针作为形参或者函数返回值,这是由于值拷贝会有很大的消耗(比如传入传出一个大的结构体).所以在C++之中使用引用作为函数参数和返回值的目的和使用指针是一样的.而且形式上更加直观,所以C++提

C++中 简单查看临时对象,局部对象的生命周期,及拷贝构造函数(测试代码)

#include <iostream> using namespace std; class A {     public: A(int a = 5) {     cout<<"A constructor "<<this<<endl; } ~A() {     cout<<"A destructor "<<this<<endl; } A(const A & r) {     

php静态动态对象及json格式

1,获取键盘输入,fget(STDIN). 2,获取静态对象函数和变量的方法,(1)引入函数requery('dasda.php');(2)调用dasda::(函数,变量); 3, 静态对象如果调用的是静态变量使用$...  如果是静态的函数,不要使用$符号,直接调用名称.substr($p,0,1)截取$p字符串从0开始的第一位. 4,isset()检测变量 是否设置并且不是null. 5,isset... ? ... : ...相当于if()....else... 6,isset是用来检测变

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

jQuery.support是用功能检测的方法来检测浏览器是否支持某些功能.针对jQuery内部使用. 我们先来看一些源码: jQuery.support = (function( support ) { ...... return support;})( {} ); jQuery.support其实就是一个json对象.在火狐浏览器下,打印出support对象: 接下来,我们来看它的源码 jQuery.support = (function( support ) { var input = d