码迷,mamicode.com
首页 > 其他好文 > 详细

一个类成员函数的局部静态变量问题

时间:2014-11-07 00:48:15      阅读:244      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   io   color   ar   os   使用   sp   

  之前工作中遇到一个问题,就像题目中描述的那样,看起来题目有些拗口复杂,这里解释下,当时遇到的需求需要这样处理:调用某个类对象的某个成员函数时,第一次有具体意义的,其他时候都是保持不变的、无意义的。这个需求可以看做是在调用某成员函数时,第一次进行初始化,其他时候不进行操作,即在首次调用时进行初始化,根据这点,很容易想到c/c++里面的static变量,它的作用是保持变量内容的持久,存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。根据需求,使用static局部变量,写下如下代码:

 1 class T
 2 {
 3 public:
 4     T(const char * pstr):value(pstr){}
 5     void Print()const;
 6 private:
 7     string value;
 8 };
 9 
10 void T::Print()const
11 {
12     static bool bFirstCall = true;
13     if(bFirstCall)
14     {
15         cout<<"first Call "<<value<<endl;
16         bFirstCall = false;
17     }
18     else
19     {
20         cout<<"not first Call "<<value<<endl;
21     }
22 }

即在类的成员函数中定义一个局部的静态变量,使得第一次调用进行初始化,用以区分是否是第一次调用,之后运行else分支。运行下面的测试代码,输出结果见下图:

 1 int _tmain(int argc, _TCHAR* argv[])
 2 {
 3     T t1("Grubby");
 4     t1.Print();
 5     t1.Print();
 6 
 7     T t2("Moon");
 8     t2.Print();
 9     t2.Print();
10 
11     return 0;
12 }

bubuko.com,布布扣

通过输出可以看到,t1得到了想要的结果,但是两次t2.Print()都打印 "not first Moon",这说明此时 bFirstCall 还是false。于是在Print函数中打印bFirstCall地址的代码:

 1 void T::Print()const
 2 {
 3     static bool bFirstCall = true;
 4     printf("addr of bFirstCall is %x\n", &bFirstCall);
 5     if(bFirstCall)
 6     {
 7         cout<<"first Call "<<value<<endl;
 8         bFirstCall = false;
 9     }
10     else
11     {
12         cout<<"not first Call "<<value<<endl;
13     }
14 }

再次运行输出如下:

bubuko.com,布布扣

看到四次调用Print函数时打印的bFirstCall的地址相同,这说明类成员函数中的局部静态变量同样属于此函数,而不属于某个对象,不会因为重新定义一个t2对象,第一次调用 t2.Print()时 bFristCall 是 true,不管是哪个T类对象,只在第一次调用 Print()时,bFirstCall == ture。于是无奈对程序进行了修改,将bFristCall定义为类的静态成员,每次构造函数是将其重置为true:

 1 class T
 2 {
 3 public:
 4     T(const char * pstr):value(pstr){ bFirstCall = true;}
 5     void Print()const;
 6 private:
 7     string value;
 8     static bool bFirstCall;
 9 };
10 bool T::bFirstCall;
11  
12 void T::Print()const
13 {
14     if(bFirstCall)
15     {
16         cout<<"first Call "<<value<<endl;
17         bFirstCall = false;
18     }
19     else
20     {
21         cout<<"not first Call "<<value<<endl;
22     }
23 }

运行测试代码可以得到想要的结果:

bubuko.com,布布扣

但是这里又出现了新的问题,即每次构造函数是将bFirstCall重置为true时,如果新定义一个对象,并且没有调用Print()函数,那么再次调用之前定义对象的Print()函数,会产生与预期相反的结果,考虑如下测试代码:

 1 int _tmain(int argc, _TCHAR* argv[])
 2 {
 3     T t1("Grubby");
 4     t1.Print();
 5     t1.Print();
 6 
 7     T t2("Moon");
 8     t1.Print();
 9 
10     return 0;
11 }

运行输出如下:

bubuko.com,布布扣

避免这种情况,目前只能保证顺序的对每个对象进行类似Print这样函数的初始化调用,还没有想到好的解决办法。

一个类成员函数的局部静态变量问题

标签:des   style   blog   io   color   ar   os   使用   sp   

原文地址:http://www.cnblogs.com/Tour/p/4080212.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!