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


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


    代码如下 

     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 }
  • 相关阅读:
    浅析AI人脸识别/车辆识别智能分析网关的深度学习算法及应用场景
    浅析基于AI智能识别技术的明厨亮灶智能化监管方案
    AI人脸识别/车辆识别智能分析网关微信端告警消息推送的开发流程
    AI车辆检测/人脸检测智能分析网关新增烟火检测识别与烟火告警
    状态压缩1815. 得到新鲜甜甜圈的最多组数
    数位DP2出现的次数
    状态压缩解题技巧
    数位DP6151. 统计特殊整数
    数位DP600. 不含连续1的非负整数
    状态压缩1755. 最接近目标值的子序列和
  • 原文地址:https://www.cnblogs.com/iamfy/p/2471224.html
Copyright © 2020-2023  润新知