6.3 临时对象

Q1:讨论一下三种语句产生临时对象的情况

    //1.
         T c = a + b;
    //2. 
        c = a + b;
    //3.
         a + b;
  • 第一种情况,实现时不会产生临时对象,可能会直接以拷贝构造的情况,将 a + b 的值放入 c 中,或是直接进行NRV优化,导致直接在对象 c 中求值操作

以下讨论另外两种情况



Q2:对 c = a + b 的情况

• 这种情况下会产生临时对象,具体代码情况如下:

    // T temp = a + b;
    T temp;
    temp.oprator+(a,b);    // (1)
    //c = temp;
    c.operator=(temp);     // (2)
    temp.T::~T()

• 上述的句子(1),未构造的临时对象被赋值给operator+(),这意味着:表达式的结果被复制构造至临时对象中,或者以临时对象进行NRV

• 直接传递 c 到运算符函数(2)中都是有问题的,因为该对象不是一个新定义的对象,而运算符函数不为其外加参数调用析构函数,所以在调用运算符函数前必须要先调用析构函数

• 因此,该语句将会被转换为如下形式:

        c.T::~T();
        c.T::T(a + b);          //产生临时对象存储 a + b

由于原语句希望调用赋值操作符函数,而转换后的语句调用析构函数与复制构造函数,因此可能转换前后语意不同,是不安全的,而且会产生临时对象

• T c = a + b 总是比 c = a + b 更有效的被编译器转换出来



Q3:对 a + b 的情况

• 会产生临时对象用来存放其值,这种情况下重点关注“临时对象的生命期

• 考虑以下例子:

Eg:

        string s,t;
        print("%s\n",s + t);

其中 s + t 将产生一个临时对象,分析该临时对象的生命期

• 下面是对该算是的一个可能的早期标准转换,虽然语法正确,但是很有问题:

Eg:

        string temp1 = operator+(s,t);
        const char * temp2 = temp1.operator const char*();   //转换操作符

        temp1.~string();     //销毁temp1

        printf("%s\n",temp2);      //此时temp2 指向一个被释放的内存

• C++ 标准规定,临时对象的摧毁应该是对完整表达式求值过程中的最后一个步骤

• 当临时性对象是根据程序的执行期语意,有条件的被产生出来时,临时对象的生命规则就有些复杂

Eg:

    if(s + t || u + v);

只有当 s + t 的值为 false 时,才会计算 u + v 的值。因此,必须先知道临时对象是否被产生,才能确定是否应该在表达式结束前销毁临时对象

• 解决方法是:某些形式的条件测试必须被安插进来,以决定是否要摧毁和第二个算式有关的临时对象

• 临时对象的声明规则有两个例外:

1. 当表达式被用来初始化一个对象时,要求持有该表达式执行结果的临时对象,应该存留到对象的初始化操作完成为止。但注意以下情况:

Eg:

            string n,s;
            cpmst char * ns = n + s;

        //会转化为如下情况:

            string temp;
            operator+(temp,n,s);
            ns = temp.string::operator char *();

         //此时对象的初始化操作已完成,才销毁临时对象,但是该销毁操作将会导致 ns 指向一个未定义的堆内存
            temp.string::~string();         

2. 当一个临时对象被一个引用绑定时,此时临时对象将残留,直到该引用的生命结束,或者临时对象的 scope 结束。如:

Eg:

            const string &space = " ";

            //会转化为如下情况:

            string temp;
            temp.string::string(" ");
            const string & space = temp;

此时如果销毁临时对象temp,则该引用将没有任何用处

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值