0. 问题:下面的程序输出什么?为什么?
#include <stdio.h>
class Test
{
private:
int mi;
public:
Test(int i)
{
mi = i;
}
Test()
{
Test(0);
}
void print()
{
printf("mi = %d\n", mi);
}
};
int main()
{
Test t;
t.print();
return 0;
}
输出结果:
mi = -1216962560
- 程序意图:在Test()中以0作为参数调用Test(int i), 将成员变量mi的初始值值为0。
- 运行结果:成员变量mi的值为随机值。
为什么会这样???
1. 思考:构造函数是一个特殊函数,因此:
- 是否可以直接调用? ——可以(构造函数可以自动调用和手动调用)
- 是否可以在构造函数中调用构造函数?——(编译器编译可以通过)
- 直接调用构造函数的行为是什么?后果是什么?
答案:
- 直接调用构造函数将产生一个临时对象
- 临时对象的生命周期只有一条语句的时间,过了这一条语句的时间,临时对象自动被析构函数析构而不复存在
- 临时对象的作用域只在一条语句中
- 临时对象是C++中值得警惕的灰色地带
编程说明:去掉临时变量
#include <stdio.h>
class Test
{
private:
int mi;
void init(int i) // 添加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
2. 编译器的行为
现代C++编译器在不影响最终执行结果的前提下,会尽力减少临时对象的产生!!!
3. 小结
- 直接调用构造函数将会产生一个临时对象
- 临时对象是性能的瓶颈,也是bug的来源之一
- 现代C++编译器会尽力避开临时对象
- 实际工程开发中需要人为的避开临时对象,因此,在写代码和在设计上要有意识的避开临时对象