您的位置:首页 > 编程语言 > C语言/C++

《 C++深度剖析》学习日志十八——神秘的临时对象

2018-02-13 08:52 399 查看
        下面我们来学习C++中最神秘的临时对象,那么临时对象是什么呢?#include<stdio.h>
class Test
{
int mi;
public:
Test(int i)
{
mi = i;
}
Test()
{
Test(0);//得到一个临时对象,过了这一行,临时对象就析构了,这一行依旧等价于//Test(0);
}
void print()
{
printf("mi = %d\n", mi);
}
};
int main()
{
Test t;

t.print();

return 0;
}
我们来解读一下程序意图:在Test()中以0作为参数调用Test(int i),目的是将成员变量mi的初始值设置为0.



但结果很出乎意料,mi为随机值。究竟哪里出错了呢?
下面我再提出三个问题:
        *构造函数是否可以直接调用?
        *是否可以在构造函数中调用构造函数?
        *直接调用构造函数的行为是什么?
前两个问题的答案在上面的例子中得到了体现,那最后一个问题的答案是什么?
        *直接调用构造函数将产生一个临时对象
       * 临时对象的生命周期只有一条语句的时间
       * 临时对象的作用域只在一条语句中
       * 临时对象是C++中值得警惕的灰色地带
解决方案:#include<stdio.h>
class Test
{
int mi;

void init(int i)
{
mi = i;
}
public:
Test(int i)
{
init(i);
}
Test()
{
init(0);
}
void print()
{
printf("mi = %d\n", mi);
}
};
int main()
{
Test t;

t.print();

return 0;
}输出结果便是mi = 0了



通过下面这段代码,我们就能看清楚临时对象的生成与销毁了。#include<stdio.h>
class Test
{
int mi;

void init(int i)
{
mi = i;
}
public:
Test(int i)
{
printf("Test(int i)\n");
init(i);
}
Test()
{
printf("Test()\n");
init(0);
}
void print()
{
printf("mi = %d\n", mi);
}
~Test()
{
printf("~Test()\n");
}
};
int main()
{
printf("main begin\n");

Test().print();
Test(10).print();

printf("main end\n");

return 0;
}


直接调用构造函数产生临时对象,赋值完了之后临时对象被消除,说白了,没什么用,这个只是学习历程,请大家提高警惕,在工作中尽量避免临时对象的生成。编译器也会尽量减少临时对象的产生#include<stdio.h>
class Test
{
int mi;
public:
Test(int i)
{
printf("Test(int i) : %d\n", i);
mi = i;
}
Test()
{
printf("Test()\n");
mi = 0;
}
void print()
{
printf("mi = %d\n", mi);
}
~Test()
{
printf("~Test()\n");
}
};
int main()
{
Test t = Test(10);

return 0;
}
Test t = Test(10);这一句话我们来进行解读    1.生成临时对象 2.用临时对象初始化t对象 ==》调用拷贝构造函数
但实际是这样子吗?
C++编译器会尽力杜绝临时对象的产生,因为临时对象会带来性能上的问题
上面那一句等价于Test t(10);


#include<stdio.h>
class Test
{
int mi;
public:
Test(int i)
{
printf("Test(int i) : %d\n", i);
mi = i;
}
Test()
{
printf("Test()\n");
mi = 0;
}
void print()
{
printf("mi = %d\n", mi);
}
~Test()
{
printf("~Test()\n");
}
};

Test func()//生成一个Test类的临时对象,并返回这个对象
{
return Test(20);
}
int main()
{
Test t = Test(10);
Test tt = func();//用生成的临时对象来初始化tt。但实际是编译器做出了优化
                    //==》Test tt = Test(20);==》Test tt = 20;

    t.print();
tt.print();
return 0;
}


结果并没有调用拷贝构造函数,所以说编译器对其进行了优化。

小结

        *直接调用构造函数将产生一个临时对象
        *临时对象是性能的瓶颈,也是bug的来源之一
        *现代C++编译器会尽力避开临时对象
        *同时也需要人为的避开临时对象

以上资料均来自狄泰,群号:199546072,志同道合的朋友可以加我:
 qq:335366243
 微信:zhong_335366243       
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: