博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

生命期是个不可大意的问题

Posted on 2012-04-26 13:03  舒方小院  阅读(380)  评论(0编辑  收藏  举报

中午同事考了一个问题,其实很简单,但一时间没看出来,仔细回味,发现有点味道。


代码如下 

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 int main()
 7 {
 8     const char * pCArray = string("hello").c_str();
 9     cout << pCArray << endl;
10     return 0;
11 }

 

问这样的做法是否有问题?

 

其实是有问题的,这里涉及到两个关于生命期的问题:

1. string对象的c_str()方法,返回的C型字符串(以\0结尾的字符数组),其生命期是由该对象维护的。 

2.  在第8行的表达式中,string("hello")是一个临时对象,而该临时对象的生命期,在赋值语句执行完后就已经结束了。

因此,在第九行pCArray指向的那块区域,已经是个无效的内存区域,这样的做法是错误的,也是危险的。

 

基本功就在于对于小概念的牢固掌握啊!

 

附:C++ 临时对象的生命周期

有关临时对象的生命周期有三种情况:

1)一般情况:临时性对象的被摧毁,应该是对完整表达式(full-expression)求值过程中的最后一个步骤。该完整表达式造成临时对象的产生。
例:

 1 #include <iostream>
 2 using namespace std;
 3 class A
 4 {
 5 public:
 6    A(int i): m_i(i)
 7    {  cout << "A(): " << m_i << endl;
 8    }
 9    ~A()
10    {  cout << "~A(): " << m_i << endl;
11    }
12    A operator+(const A& rhs)
13    {  cout << "A operator+(const A& rhs)" << endl;
14       return A(m_i + rhs.m_i);
15    }
16    int m_i;
17 };
18 int main()
19 {  A a1(1), a2(2);
20    a1 + a2;
21    cout << "------------------------------------" << endl; 
22    //运行到这里,a1 + a2产生的临时变量已经被释放
23    return 0;
24 }

 

 

2)凡含有表达式执行结果的临时性对象,应该存留到object的初始化操作完成为止。
例:

 1 #include <iostream>
 2 using namespace std;
 3 class A
 4 {
 5 public:
 6    A(int i = 0): m_i(i)
 7    {  cout << "A(): " << m_i << endl;
 8    }
 9    ~A()
10    {  cout << "~A(): " << m_i << endl;
11    }
12    A operator+(const A& rhs)
13    {  cout << "A operator+(const A& rhs)" << endl;
14       return A(m_i + rhs.m_i);
15    }
16    A& operator=(const A& rhs)
17    {  cout << "A& operator=(const A& rhs)" << endl;
18       m_i += rhs.m_i;
19       return *this;
20    }
21    int m_i;
22 };
23 int main()
24 {  A a1(1), a2(2);
25    A a3;
26    a3 = a1 + a2; 
27    //a1 + a2产生的临时变量在a3的赋值操作完成后,才释放
28    return 0;
29 }

 

 

3)如果一个临时性对象被绑定于一个reference,对象将残留,直到被初始化之reference的生命结束,或直到临时对象的生命范畴(scope)结束——视哪一种情况先到达而定。
例:

 1 #include <iostream>
 2 using namespace std;
 3 class A
 4 {  friend ostream& operator<<(ostream& os, const A&);
 5 public:
 6    A()
 7    {
 8    }
 9    A(const A&)
10    {  cout << "A(const A&)" << endl;
11    }
12    ~A()
13    {  cout << "~A()" << endl;
14    }
15 };
16 ostream& operator<<(ostream& os, const A&)
17 {  os << "ostream& operator<<(ostream& os, const A&)" << endl;
18    return os;
19 }
20 const A& f(const A& a)
21 {  return a;
22 }
23 int main(int argc, char* argv[])
24 {
25    {  const A& a = A();
26       cout << "-------------------" << endl;
27    }
28    //直到被初始化之reference的生命结束
29   cout  << f(A()) << endl; 
30    //直到临时对象的生命范畴(scope)结束:
31    //临时对象的const引用在f的参数上(而不是返回值)。
32    //这个引用在f()返回的时候就结束了,但是临时对象未必销毁。
33    cout << "-------------------" << endl;
34   return 0;
35 }