对象优化相关"/>
【C++】对象优化相关
目录
- 对象使用过程中其背后调用了哪些方法
- 函数调用过程中对象背后的调用方法
橙色
对象使用过程中其背后调用了哪些方法
t2和t3均调用了拷贝构造。值得看的是t4,构造t4的过程只调用了构造函数。这是C++编译器对于对象构造的优化:用临时对象(Test(20))生成新对象的时候,临时对象就不产生了,直接构造新对象就可以了
class Test
{
public:Test(int a=10):m(a){cout << "Test()" << endl;}~Test(){cout << "~Test()" << endl;}Test(const Test &t):m(t.m){cout << "Test(const Test &)" << endl;}operator=(const Test &t){cout << "operator=" << endl;m =t.m;return *this;}
private:int m;
};int main() {Test t1;Test t2 = t1;Test t3 = t1;Test t4 = Test(20);//与Test t4(20);没有区别的cout << "----------" << endl;return 0;
}
可以看到t2 = t1;这一行调用了赋值操作函数,t2 = Test(30);这一行先是调用了构造函数生成了临时对象,接着调用了赋值操作函数,最后是临时对象调用了析构函数。
int main() {Test t1;Test t2 = Test(20);cout << "----------" << endl; t2 = t1;t2 = Test(30);cout << "----------" << endl;return 0;
}
还有如下的两种方法,第一种用指针去指向一个临时对象是不可行的
,因为临时对象的生存周期是该语句,执行到下一语句时就会被释放掉,此时p就成了一个野指针。而第二种则是引用,相当于给临时对象起了一个名字,此时这个临时对象的生命周期就变成了引用变量ref的生存周期
Test *p = &Test(40);
const Test &ref = Test(50);
函数调用过程中对象背后的调用方法
分析一下这段代码,首先主函数中,t1和t2调用了构造函数;接着把t1传入函数的过程中,通过拷贝函数把t1 拷贝 给了形参t,为什么是拷贝而不是赋值呢?因为赋值是针对两个已经存在的函数对象,而形参t还未定义;接着temp调用了 构造函数 ,接着在return temp的过程中再次通过拷贝函数拷贝了一个临时对象,因为temp是函数中的一个临时变量,它的作用域仅限于函数体内;接着形参t和临时变量temp分别调用了析构函数;接着把临时对象赋值给t2,调用了赋值函数;接着临时对象、t2、t1依此调用了析构函数。
可以看到,上面这段短短的代码总共调用了11次函数,这样对内存的消耗无疑是巨大的。
该怎么改进呢?遵循以下三点:
1、函数参数传递过程中,对象优先按引用传递,不要按值传递。
上面的形参改为引用类型,可以减掉形参的拷贝构造和形参的析构这两个函数调用。
通过第1步优化,这段代码仅需调用9个函数
2、函数返回对象的时候,应该优先返回一个临时对象,而不要返回一个定义过的对象。
如下图这样,原本的流程是在Getobject函数中构造一个临时对象,但因为该临时对象无法走出Getobject函数作用域,所以要用该临时对象拷贝一个新对象返回。但前面已经学习过,当通过临时对象来拷贝一个新对象时,编译器会进行优化,不生成该临时对象,而是直接通过构造函数来构造新对象(该新对象是要返回给main函数中调用了该函数的,其生命周期仅限于main函数调用了该函数的那一语句)。因此就减少了Getobject函数中temp临时对象的构造和析构,又减少了两个函数的调用。
通过第2步优化,这段代码仅需调用7个函数
3、接收返回值是对象的函数调用的时候,优先按初始化的方式接收,不要按赋值的方式接收。
按如下的方式写,Getobject返回的是一个临时对象,又是通过临时对象拷贝构造一个新对象,所以该临时对象不生成,直接构造出一个新的对象
通过第3步,又减少了Getobjct(t1)这个临时对象的生成与析构,以及赋值函数的调用,共3个函数的调用,此时该段代码仅需调用4个函数即可
更多推荐
【C++】对象优化相关
发布评论