#include <iostream>
using namespace std;
class Test {
public:
Test(int data = 10) :ma(data)
{
cout << "Test(int)" << endl;
}
~Test()
{
cout << "~Test(int)" << endl;
}
Test(const Test &obj)
{
cout << "Test(const Test &obj)" << endl;
this->ma = obj.ma;
}
void operator=(const Test &obj)
{
cout << "=operator(const Test &obj)" << endl;
if (this == &obj)
return;
this->ma = obj.ma;
}
private:
int ma;
};
int main()
{
cout << "+++++++++++++++" << endl;
Test t1 = Test(50);
cout << "+++++++++++++++" << endl;
Test t2;
cout << "+++++++++++++++" << endl;
t2 = Test(50);
cout << "+++++++++++++++" << endl;
t2 = 50;
cout << "+++++++++++++++" << endl;
return 0;
}
以上代码的运行结果是:
当我们使用Test t1 = Test(50);拷贝构造了同类型的对象的时候临时对象不产生,故只调用了一次t1的构造函数。
当我们使用t2 = Test(50)的时候因为此时t2对象已经存在,这里并没有拷贝构造的操作,故需要临时变量的产生来给t2做等号赋值运算。然后语句结束后临时对象就被析构。
t2 = 50 同理。
然后程序的最后析构为t2的析构和t1的析构。
那么我们可以得出结论:如果临时对象"拷贝构造"同类型的对象那么临时对象不产生。
临时对象的函数应用总结
引例子:
我们在上面代码的基础上增加俩个函数
类内函数:
int getData()
{
return ma;
}
类外函数获取Test对象
Test GetTestObject1(Test t)
{
int val = t.getData();
Test tmp(val);
return tmp;
}
此时我们调用GetTestObject1函数来看有多少个构造和析构
主函数:
int main()
{
Test t1;
Test t2 = GetTestObject1(t1);
return 0;
}
结果:
一共有八行
第一行:t1的构造函数。
第二行:使用t1给参数t进行拷贝构造。
第三行:函数中的tmp的默认的构造函数。
第四行:函数中的tmp给main栈区的t2的拷贝构造(因为tmp是局部变量,函数调用后它的声明周期就结束了,如果要在main函数中取得函数中的对象,只能在tmp被析构前把它的内容拷贝构造给t2,)这里还因为临时对象给相同类型的对象拷贝构造,并不真正的产生临时变量,故这里相当于tmp直接给t2拷贝构造。
第五行:由于函数的执行完毕需要执行t和tmp的析构,这一行是析构tmp局部对象。
第六行:析构t
第七行:析构t2
第八行:析构t1
优化1:将参数的类型设置为引用
修改函数:
Test GetTestObject2(Test &t)
{
int val = t.getData();
Test tmp(val);
return tmp;
}
运行结果:
可以看到经过这么修改,8行变为6行,少了参数t的构造和析构,避免了不必要的开销,优化了对象方法调用的过程。
优化2:根据(临时对象拷贝构造相同类型的对象的时候,并不产生新的对象)的原理我们可以将函数的返回值设置为临时对象(返回临时对象)。
代码:
Test GetTestObject3(Test &t)
{
int val = t.getData();
return Test(val);
}
这样之后结果:
这样之后从上次优化后的六行变为四行。又优化了tmp的构造和析构,又进一步减少了对象方法调用的开销。
上诉中所有的测试用例代码总结:
#include <iostream>
using namespace std;
class Test {
public:
Test(int data = 10) :ma(data)
{
cout << "Test(int)" << endl;
}
~Test()
{
cout << "~Test(int)" << endl;
}
Test(const Test &obj)
{
cout << "Test(const Test &obj)" << endl;
this->ma = obj.ma;
}
void operator=(const Test &obj)
{
cout << "=operator(const Test &obj)" << endl;
if (this == &obj)
return;
this->ma = obj.ma;
}
int getData()
{
return ma;
}
private:
int ma;
};
Test GetTestObject1(Test t)
{
int val = t.getData();
Test tmp(val);
return tmp;
}
Test GetTestObject2(Test &t)
{
int val = t.getData();
Test tmp(val);
return tmp;
}
Test GetTestObject3(Test &t)
{
int val = t.getData();
return Test(val);
}
int main()
{
//1
/*cout << "+++++++++++++++" << endl;
Test t1 = Test(50);
cout << "+++++++++++++++" << endl;
Test t2;
cout << "+++++++++++++++" << endl;
t2 = Test(50);
cout << "+++++++++++++++" << endl;
t2 = 50;
cout << "+++++++++++++++" << endl;*/
//2
Test t1;
Test t2 = GetTestObject3(t1);
return 0;
}
总结:
1,函数调用传参,如果是对象传递引用。(少一次构造和一次析构的对象方法开销)。
2,函数需要返回对象值时候,返回临时对象(少一次局部对象的构造和析构)。