您的位置:首页 > 其它

默认成员函数的几种调用情景

2017-07-16 16:09 197 查看


C++中默认成员函数的调用情况


调用情况分为两种:

1,普通调用(即没有优化的调用情况)举例来说明

下面这个类中的默认成员函数只做了一件事就是调用时打印各自的函数名称。
class AA
{
public:
AA()
{
cout << "构造函数" << endl;
}
AA(const AA& a)
{
cout << "拷贝构造函数" << endl;
}
~AA()
{
cout << "析构函数" << endl;
}
void operator=(const AA a)
{
cout << "赋值运算符重载" << endl;
}
};


第一种调用情况如图,编译器没有进行任何优化。函数调用时先构造了a1,再把a1当参数传给了函数f这里是用a1拷贝构造了a ,在返回a时利用a拷贝构造了一块临时空间tmp。返回之后要销毁栈帧了,所以这时就开始调用析构函数了,由于栈是先进后出的原则,所以这时先析构了拷贝构造出来的a。再进行赋值运算符的重载,函数f的返回值被利用完了,析构a拷贝构造出来的tmp,最后Test1函数调用完毕该销毁栈帧了,这时将a1析构。


 

这是第一种情况运行完成后所执行的结果



编译器有优化时候的调用 

编译器有优化的情景,这段代码先构造了a1,再以a1为参数传入函数f拷贝构造了a,函数返回a,在返回a时利用a拷贝构造了一块临时空间tmp。返回之后要销毁栈帧了,所以这时就开始调用析构函数了,由于栈是先进后出的原则,所以这时先析构了拷贝构造出来的a。因为这里的a2并没有被创建出来,所以这是利用函数f返回值来拷贝构造a2,在这里编译器会进行优化,编译器会将函数返回时的tmp的拷贝构造和利用返回值拷贝构造a2优化为一次拷贝构造,Test2代码执行完毕之后销毁栈帧,先将a2析构后将a1析构。

 


函数执行后的结果。

 


还有一种较为复杂的调用(复合函数形式的调用) 

编译器有优化的情景,这段代码先构造了a1,再以a1为参数传入函数f拷贝构造了a,函数返回a,在返回a时利用a拷贝构造了一块临时空间(临时空间具有常性)tmp。函数f执行完该销毁栈帧了,这时先析构了拷贝构造出来的a,再以tmp作为下一次调用函数f的参数拷贝构造a,这里编译器做了一次优化,编译器将两次拷贝构造优化为一次(即没有创建对临时对象的拷贝构造而是直接拷贝构造了下一次的形参a)。到了这里就和上面的情况一模一样了

 


此次代码运行的结果是




总结

这几种情景下对四个默认成员函数的调用其实很好分析,难就难在编译器会对某些情景进行悄无声息的优化,所以分析是一定要考虑清楚编译器是否进行了优化。编译器进行优化的原则很简单,就是代码在同一行它才会进行优化。这里编译器对拷贝构造优化的几率最多,所以重点考虑编译器是怎么对拷贝构造进行优化的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: