更多课程 选择中心

C/C++培训
达内IT学院

400-996-5531

C++中的返回值优化

  • 发布:C++培训
  • 来源:资料库
  • 时间:2017-10-10 14:08

在这篇文章里用到了以下编译器和操作系统,大家请自行安装

首先我们先来看一道题,下面的代码运行之后会输出什么结果?

我想大多数人会选A,对吗?因为foo函数在返回C类的对象时会调用拷贝构造函数来创建一个临时对象。

现在让我们编译并运行这个程序,看看输出结果是否如我们所料

$ clang++ -std=c++11 foo.cpp

$ ./a.out

Constructor

Destructor

然而,遗憾的是,事实与课本里说的并不一样,那么,为什么会这样呢?从实际编译运行的输出来看,C类的拷贝构造函数并没有被调用。

这是因为在实际工程中大多数时候C++构造对象的开销巨大,编译器为了生成高效的代码,在foo函数返回时并没有调用拷贝构造函数去生成一个临时对象,而是直接使用在foo函数内初始化的对象c1作为返回值传出去。这就是C++中的返回值优化(Return Value Optimization, RVO)。

由于较新版本的gcc/clang均已默认开启了返回值优化(即使没有加上优化选项),我们想看到书上所说的现象只能在编译的时候加上特殊选项,让编译器不要做返回值优化,操作步骤如下:

$ clang++ -std=c++11 -fno-elide-constructors foo.cpp

$ ./a.out

Constructor

Copy Constructor

Destructor

Destructor

返回值优化能在一定程度上提高程序的运行效率,但是我们在实际工程中最好不要依赖这个编译器优化特性,因为它要求的条件非常苛刻(或者说,编译器还不够聪明:P)。让我们在foo函数中加上一个无用的条件判断语句,试试编译器是否能继续应用返回值优化。

可以发现,在上面的代码中,如果编译器足够聪明,它应该能推断出foo函数只会返回c1,所以可以对foo函数应用返回值优化,那么让我们来实际编译运行一下,看看执行情况。

$ clang++ -std=c++11 -O3 foo.cpp

$ ./a.out

Constructor

Constructor

Copy Constructor

Destructor

Destructor

Destructor

$ g++ -std=c++11 -O3 foo.cpp

$ ./a.out

Constructor

Constructor

Copy Constructor

Destructor

Destructor

Destructor

可以看到,clang 5.0.0和gcc 6.3.0即使把优化选项开到最大也不能对foo函数进行返回值优化。

返回值优化还带来了一个问题,那就是拷贝构造函数和析构函数的调用变得不可预测。如果在拷贝构造函数和析构函数中存在有副作用(side-effect)的语句,就会造成不同的编译器配置编译出来的程序运行结果不一致。事实上,这是被C++11标准所允许的,下面这段话引用自C++11标准Sec 12.8 Copying and moving class objects [class.copy]

When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the copy/move constructor and/or destructor for the object have side effects.

是否调用拷贝构造函数和析构函数的决定交给了编译器实现去判断,所以在实际工程中为了写出可移植的代码,就需要避免在构造函数和析构函数中加入有副作用的语句,并且应该尽量把复杂的逻辑剥离出来,放在类的其它成员函数中实现。

原文链接:#/s/BynCMibnW

预约申请免费试听课

填写下面表单即可预约申请免费试听!怕钱不够?可就业挣钱后再付学费! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!

上一篇:教你如何养成良好的C++开发代码风格
下一篇:达内C++培训班:教你C/C++回调函数

超全的C语言标识符知识

C指针——指针类型转换

C指针——指针和结构类型的关系

C指针——数组和指针的关系

Copyright © 2023 Tedu.cn All Rights Reserved 京ICP备08000853号-56 京公网安备 11010802029508号 达内时代科技集团有限公司 版权所有

选择城市和中心
黑龙江省

吉林省

河北省

湖南省

贵州省

云南省

广西省

海南省