#include <iostream>
class Test{
int mi;
public:
Test(int i)
{ mi=i; }
Test()
{ Test(0); } //创建临时对象,生命周期和作用域是这条语句,并没有将0设置到对象。等价于空的函数体。
bois print()
{ cout<<mi<<endl; }
};
int main()
{
Test t;
t.print();
return 0;
}
程序意图:在Test()中以0作为参数调用Test(int i)
将成员变量mi的初始值设置为0.
运行结果: 是随机值
直接调用构造函数将产生一个临时对象,临时对象的生命周期只有一条语句的时间,临时对象的作用域只在一条语句中,临时对象是c++中值得警惕的灰色地带
解决方案:增加一个init()函数
#include <iostream>
class Test{
int mi;
void init(int i)
{
mi=i;
}
public:
Test(int i)
{ // mi=i;
init(i);
}
Test()
{ //Test(0);
init(i); } //创建临时对象,生命周期和作用域是这条语句,并没有将0设置到对象。等价于空的函数体。
bois print()
{ cout<<mi<<endl; }
};
int main()
{
Test t;
t.print();
return 0;
}
*************************************
#include <iostream>
class Test{
int mi;
void init(int i)
{
mi=i;
}
public:
Test(int i)
{ // mi=i;
init(i);
}
Test()
{ //Test(0);
init(i); } //创建临时对象,生命周期和作用域是这条语句,并没有将0设置到对象。等价于空的函数体。
bois print()
{ cout<<mi<<endl; }
};
int main()
{
cout<<"begin"<<endl;
Test ();
Test (10); //直接调用构造函数,产生临时对象
cout<<"end"<<endl;
return 0;
}
现代c++编译器在不影响最终执行结果的前提下,会尽力减少临时对象的产生。
Test t=Test(10); //1、生成临时对象 2,用临时对象初始化t对象 调用拷贝构造函数
但是编译器没有按上面的做法,编译器没有生成临时对象。而是:
Test t= Test(10); 编译器的做法 ==> Test t = 10;
++++++********************************************
Test func()
{
return Test(20);
}
int main()
{
Test t=func(); // 用func()的返回值(临时对象)初始化 t 。等价于==>Test t=Test(20) ==> Test t=20
t.print();
}
直接调用构造函数将产生一个临时对象,临时对象是性能的瓶颈,也是bug的来源之一,现代c++编译器会尽力避开临时对象,实际工程开发中需要人为的避开临时对象。