C++返回值优化(RVO)

2019-12-11  本文已影响0人  Magic11
RVO是C++在处理一个函数返回类对象并将返回值赋给另一个对象时,为了减少拷贝构造次数以及析构次数而采用的一种编译器优化技术。

如下一段代码:

#include <iostream>

using namespace std;

int g_construct_count = 0;
int g_copy_construct_count = 0;
int g_destruct_count = 0;

struct Widget
{
    Widget(){
        cout << "construct count:" << ++g_construct_count << endl;
    }

    Widget(const Widget& widget){
        cout << "copy construct count:" << ++g_copy_construct_count << endl;
    }

    ~Widget() {
        cout << "destruct count: " << ++g_destruct_count << endl;
    }
};

Widget getWidget() {
    Widget w;
    return w;
}

int main() {
    Widget widget = getWidget();

    return 0;
}

下面分别看一下上述代码在g++和vs2013上的运行结果
1)g++在关闭RVO的情况下

@ubuntu:~/work/test/rvo-test$ g++ rvo.cpp -o rvo -fno-elide-constructors
@ubuntu:~/work/test/rvo-test$ ./rvo
construct count:1               //首先在getWidget函数中创建w对象,调用一次构造函数
copy construct count:1          //通过w对象创建一个临时的返回值对象temp,调用一次拷贝构造函数
destruct count: 1               //释放w对象
copy construct count:2          //通过临时的对象temp创建widget对象,调用一次拷贝构造函数
destruct count: 2               //释放临时对象temp
destruct count: 3               //释放对象widget

2)g++在不关闭RVO的情况下(默认是不关闭的)

@ubuntu:~/work/test/rvo-test$ g++ rvo.cpp -o rvo
@ubuntu:~/work/test/rvo-test$ ./rvo
construct count:1
destruct count: 1

在vs下代码调用略有差异

void test() {
    Widget widget = getWidget();
}

int main() {

    test();

    getchar();
    return 0;
}

3)vs2013在debug情况下的运行结果

construct count:1
copy construct count:1
destruct count: 1
destruct count: 2

4)vs2013在release情况下的运行结果

construct count:1
destruct count: 1

vs2013 debug模式下对应的伪代码如下:

void getWidget(const Widget &result)
{
    Widget w;                   //创建w对象
    result(w);                  //用w对象拷贝构造result对象;
    w.Widget::~Widget();        //w对象析构
    return;
}

若将getWidget函数修改为

Widget getWidget() {
    return Widget();
}

则vs2013在debug模式下的运行结果如下:

construct count:1
destruct count: 1

其对应的伪代码如下:

void getWidget(const Widget &result)
{
    result();             
    return;
}

NRVO模式则能将如下代码:

Widget getWidget() {
    Widget w;
    return w;
}

优化成上述伪代码形势
参考:
https://blog.csdn.net/rlyhaha/article/details/80381170
http://www.voidcn.com/article/p-nughucjy-bga.html

上一篇 下一篇

猜你喜欢

热点阅读