测试环境:win10 vs2013 初始代码:
代码语言:javascript复制#include <iostream>
using namespace std;
class Test {
private:
int ma;
public:
Test(int data = 10) :ma(data) {
cout << "Test(int)" << endl;
}
Test(const Test& t) :ma(t.ma) {
cout << "Test(const Test&)" << endl;
}
~Test() {
cout << "~Test()" << endl;
}
Test& operator=(const Test& t) {
ma = t.ma;
cout << "operator=" << endl;
return *this;
}
int getData() {
return ma;
}
};
Test getObject(Test t) {
int val = t.getData();
Test res(val);
return res;
}
int main() {
Test t1(10);
Test t2;
t2 = getObject(t1);
return 0;
}
执行结果: 上面短短的三行代码,背后居然11次的函数调用,效率太低了!!!
一、函数参数要求传入对象时,使用引用传递
代码语言:javascript复制#include <iostream>
using namespace std;
class Test {
private:
int ma;
public:
Test(int data = 10) :ma(data) {
cout << "Test(int)" << endl;
}
Test(const Test& t) :ma(t.ma) {
cout << "Test(const Test&)" << endl;
}
~Test() {
cout << "~Test()" << endl;
}
Test& operator=(const Test& t) {
ma = t.ma;
cout << "operator=" << endl;
return *this;
}
int getData() {
return ma;
}
};
// 相对上边的代码 仅仅是将形式参数 Test t改为Test &t
Test getObject(Test& t) {
int val = t.getData();
Test res(val);
return res;
}
int main() {
Test t1(10);
Test t2;
t2 = getObject(t1);
return 0;
}
执行结果:
可以看到,经过函数参数的优化(值传递->引用传递),减少了一次临时对象构造和析构的函数开销。 相对于之前,只有9次的函数调用,减少了两次!!!
二、函数返回时,返回临时对象,不要先定义对象,然后再返回。直接提前计算好构造该函数返回对象所需要的参数,直接返回临时对象。
代码语言:javascript复制#include <iostream>
using namespace std;
class Test {
private:
int ma;
public:
Test(int data = 10) :ma(data) {
cout << "Test(int)" << endl;
}
Test(const Test& t) :ma(t.ma) {
cout << "Test(const Test&)" << endl;
}
~Test() {
cout << "~Test()" << endl;
}
Test& operator=(const Test& t) {
ma = t.ma;
cout << "operator=" << endl;
return *this;
}
int getData() {
return ma;
}
};
Test getObject(Test &t) {
int val = t.getData();
// Test res(val);
// return res;
return Test(val);
}
int main() {
Test t1(10);
Test t2;
t2 = getObject(t1);
return 0;
}
执行结果:
相对于上一步优化,又减少了两次函数调用的开销!!!
三、当需要接受一个函数的返回值时,并且该返回值是一个对象,不要以赋值的方式接受,以初始化的方式接受。
代码语言:javascript复制#include <iostream>
using namespace std;
class Test {
private:
int ma;
public:
Test(int data = 10) :ma(data) {
cout << "Test(int)" << endl;
}
Test(const Test& t) :ma(t.ma) {
cout << "Test(const Test&)" << endl;
}
~Test() {
cout << "~Test()" << endl;
}
Test& operator=(const Test& t) {
ma = t.ma;
cout << "operator=" << endl;
return *this;
}
int getData() {
return ma;
}
};
Test getObject(Test &t) {
int val = t.getData();
// Test res(val);
// return res;
return Test(val);
}
int main() {
Test t1(10);
Test t2 = getObject(t1);// 初始化的方式接受
// t2 = getObject(t1); // 赋值的方式接受
return 0;
}
执行结果:
相对于初始的代码,同样是获取一个对象的功能,优化到现在只有两次的构造和两次析构的调用,程序减少了相当大的一部分的函数调用开销,程序的效率也得到了很大的提升。一次调用getObejct()函数可以减少7次的函数调用开销,那么100万次的调用,就能减少700万次的开销。量变产生质变!!! 对象优化的三条规则 1.当函数的形式参数需要传递对象时,不要用值接受,用引用接受。减少一次临时对象的构造和析构。 2.当函数的返回值为对象时,不要再函数题先定义好零时对象,然后再返回值。直接提前计算好构造该返回对象需要的参数,直接返回一个临时对象。 3.当接受函数返回值为对象的函数的返回值时,以初始化的方式接受,不要以赋值的方式接受。 tips:当以临时对象拷贝构造一个新对象时,编译器不会产生这个临时对象,直接以构造临时对象的方式直接构造新对象,减少一次临时对象的构造和析构。