本文内容取自于对狄泰学院 唐佐林老师 C++深度解析 课程的学习总结
有趣的问题
下面的程序输出什么?为什么?
运行结果
从实验结果可以看出,mi的值为一个随机数
发生了什么
程序意图:
- 在 Test() 中以 0 作为参数调用 Test(int i)
- 将成员变量 mi 的初始值设置为 0
运行结果:
- 成员变量 mi 的值为随机值
思考
构造函数 是一个特殊的函数
- 是否可以 直接调用 ?
- 是否可以在 构造函数中调用构造函数?
- 直接调用构造函数的行为是什么?
答案
- 直接调用构造函数将产生一个 临时对象
- 临时对象的 生命周期只有一条语句的时间
- 临时对象的 作用域只在一条语句中
- 临时对象是C++中 值得警惕 的灰色地
编程实验
解决方案
定义一个私有成员函数init()来初始化私有变量 mi
#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;
}
运行结果
编译器的行为
现代C++编译器 在不影响最终执行结果的前提下,
会尽力减少临时对象的产生!!!
编程实验
神秘的临时对象
#include <stdio.h>
class Test
{
int mi;
public:
Test(int i)
{
printf("Test(int i) : %d\n", i);
mi = i;
}
Test(const Test& t)
{
printf("Test(const Test& t) : %d\n", t.mi);
mi = t.mi;
}
Test()
{
printf("Test()\n");
mi = 0;
}
int print()
{
printf("mi = %d\n", mi);
}
~Test()
{
printf("~Test()\n");
}
};
Test func()
{
return Test(20);
}
int main()
{
Test t = Test(10); // ==> Test t = 10;
Test tt = func(); // ==> Test tt = Test(20); ==> Test tt = 20;
t.print();
tt.print();
return 0;
}
运行结果:
经过编译器的优化,Test t = Test(10); 等价于 Test t = 10;
Test tt = func(); // ==> Test tt = Test(20); ==> Test tt = 20;
避免了临时对象的产生
小结
- 直接调用构造函数将产生 一个临时对象
- 临时对象是 性能的瓶颈,也是 来源之一
- 现代 C++ 编译器会尽力 避开临时对象
- 实际工程开发中需要人为的 避开临时对象