C++——关于返回值优化问题

我们知道,对于一个函数的返回值来说,其是一个对象的拷贝。并且应当是一个右值。我们现在有一个函数

A get_A()
{
    A a(1);
    return a;
}

int mian()
{
    A = get_A();
    return 0;
}

这个函数的行为应当是在函数体中构造一个a,然后在返回的时候再复制一份a。

我们的本意是仅仅的得到一份a,但是却做了重复的拷贝工作。在编译器还不是那么智能的年代,这个问题不能得到很好的解决。但是现代C++中,编译器会为我们做优化。我们如上调用这个函数,编译器我们生成的目标代码就像是直接调用了A的构造函数一样。

struct A
{
    int data;
    A() : data(0)
    { 
        cout << "construction" << endl;
    }
    A(int d) : data(d)
    {
        cout << "construction" << endl;
    }
    A(A && a) : data(a.data)
    {
        cout << "move" << endl;
    }
    A(const A & a) : data(a.data)
    {
        cout << "copy con" << endl;
    }
    ~A()
    {
        cout << "destruction" << endl;
    }
};
A get_A()
{
    A a(1);
    return a;
}
A get_A_p()
{
    return A(1);
}

int main()
{
    A a1 = get_A();
    // A a2 = get_A_p()
    cin.get();
    return 0;
}

你可以拿着这么一个简短的代码去g++, 或者clang++,或者是任何一个支持返回值优化的编译上去运行,你将会得到如下的结果。

所以说,如果有编译器的优化,在些C++代码的时候关于返回值这里可以放心的去写。效率的工作编译器为我们承担了一部分。


不过为读者困惑的是,即便关闭了编译器优化,我么得到的目标文件还是可以进行返回值优化,如果想要关闭这种优化来看一下返回值具体的运作过程,需要使用以下的命令。

 g++ main.cpp -o main -fno-elide-constructors

运行程序

 

这是一个惊人的结果!如果在对象比较大的时候还没有对应的移动构造,那么进行的无用复制可想而知。

来分析以下:

首先是函数内的A a(1) 对象,返回值用其移动构造,然后a自身销毁,返回值又移动构造给了main中的a1然后销毁。这个开销还是很大的。不过好在有编译器为我们优化,在现代C++设计中,有编译器的优化,我们可以不用在返回值的效率上杞人忧天了,岂不是十分舒服!

参考:

More Effective C++条款19,20

 g++ 关闭返回值优化_天涯Kevin的博客-CSDN博客_g++ 关闭优化

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值