为避免对临时对象进行不必要的拷贝,C++编译器常使用一种名为Copy Ellision(拷贝去除)的优化技术,该技术至少包括以下两项内容:

  1. 返回值优化(RVO),即通过将返回值所占空间的分配地点从被调用端转移至调用端的手段来避免拷贝操作。
    返回值优化包括具名返回值优化(NRVO)与无名返回值优化(URVO),两者的区别在于返回值是具名的局部变量还是无名的临时对象。
  2. 右值拷贝优化,当某一个类类型的临时对象被拷贝赋予同一类型的另一个对象时,通过直接利用该临时对象的方法来避免拷贝操作。
    这项优化只能用于右值(临时对象),不能用于左值。
如果需要测试编译器是否应用了Copy Ellision优化技术,可使用以下代码(摘自cppnext)。
#include <iostream>struct X
{X() : id(instances++){std::cout << "X" << id << ": construct\n";}X(X const& rhs) : id(instances++){std::cout << "X" << id << ": <- " << "X" << rhs.id << ": **copy**\n";++copies;}// This particular test doesn't exercise assignment, but for// completeness:X& operator=(X const& rhs){std::cout << "X" << id << ": <- " << "X" << rhs.id << ": assign\n";}~X() { std::cout << "X" << id << ": destroy\n"; }unsigned id;static unsigned copies;static unsigned instances;
};unsigned X::copies = 0;
unsigned X::instances = 0;#define CHECK_COPIES( stmt, min, max, comment )                         \
{                                                                       \unsigned const old_copies = X::copies;                              \\std::cout << "\n" comment "\n" #stmt "\n===========\n";             \{                                                                   \stmt;                                                           \}                                                                   \unsigned const n = X::copies - old_copies;                          \if (n > max)                                                        \std::cout << "*** max is too low or compiler is buggy ***\n";   \if (n < min)                                                        \std::cout << "*** min is too high or compiler is buggy ***\n";  \\std::cout << "-----------\n"                                        \<< n << "/" << max                                        \<< " possible copies made\n"                              \<< max - n << "/" << max - min                            \<< " possible elisions performed\n\n";                    \\if (n > min)                                                        \std::cout << "*** " << n - min                                  \<< " possible elisions missed! ***\n";                \
}struct trace
{trace(char const* name): name(name){std::cout << "->: " << name << "\n";}~trace(){std::cout << "<-: " << name << "\n";}char const* name;
};void sink(X a)
{trace t("sink");
}X nrvo_source()
{trace t("nrvo_source");X a;return a;
}X urvo_source()
{trace t("urvo_source");return X();
}X identity(X a)
{trace t("identity");return a;
}X lvalue_;
X& lvalue()
{return lvalue_;
}
typedef X rvalue;int main()
{// Double parens prevent "most vexing parse"CHECK_COPIES( X a(( lvalue() )), 1, 1, "Direct initialization from lvalue");CHECK_COPIES( X a(( rvalue() )), 0, 1, "Direct initialization from rvalue");CHECK_COPIES( X a = lvalue(), 1, 1, "Copy initialization from lvalue" );CHECK_COPIES( X a = rvalue(), 0, 1, "Copy initialization from rvalue" );CHECK_COPIES( sink( lvalue() ), 1, 1, "Pass lvalue by value" );CHECK_COPIES( sink( rvalue() ), 0, 1, "Pass rvalue by value" );CHECK_COPIES( nrvo_source(), 0, 1, "Named return value optimization (NRVO)" );CHECK_COPIES( urvo_source(), 0, 1, "Unnamed return value optimization (URVO)" );// Just to prove these things compose properlyCHECK_COPIES( X a(urvo_source()), 0, 2, "Return value used as ctor arg" );// Expect to miss one possible elision hereCHECK_COPIES( identity( rvalue() ), 0, 2, "Return rvalue passed by value" );
}
代码说明
  1. lvalue()函数返回struct X类型的全局变量lvalue_的引用,故lvalue()函数返回左值,可用于测试右值拷贝优化。
  2. rvalue()函数返回struct X类型的构造器所构建的临时对象,故rvalue()函数返回右值,可用于测试右值拷贝优化。
  3. nrvo_source()函数返回struct X类型的局部变量a,故nrvo_source()函数可用于测试具名返回值优化。
  4. urvo_source()函数返回struct X类型的构造器所构建的临时对象,故urvo_source()函数可用于测试无名返回值优化。
  5. 第109,110行分别用左右值来测试类对象直接初始化中的右值拷贝优化。
  6. 第112,113行分别用左右值来测试类对象拷贝初始化中的右值拷贝优化。
  7. 第115,116行分别用左右值来测试普通函数实参中的右值拷贝优化。
  8. 第118,119行分别用于测试具名返回值优化与无名返回值优化。

Windows平台下使用gcc4.6.1编译运行结果如下

X0: constructDirect initialization from lvalue
X a(( lvalue() ))
===========
X1: <- X0: **copy**
X1: destroy
-----------
1/1 possible copies made
0/0 possible elisions performedDirect initialization from rvalue
X a(( rvalue() ))
===========
X2: construct
X2: destroy
-----------
0/1 possible copies made
1/1 possible elisions performedCopy initialization from lvalue
X a = lvalue()
===========
X3: <- X0: **copy**
X3: destroy
-----------
1/1 possible copies made
0/0 possible elisions performedCopy initialization from rvalue
X a = rvalue()
===========
X4: construct
X4: destroy
-----------
0/1 possible copies made
1/1 possible elisions performedPass lvalue by value
sink( lvalue() )
===========
X5: <- X0: **copy**
->: sink
<-: sink
X5: destroy
-----------
1/1 possible copies made
0/0 possible elisions performedPass rvalue by value
sink( rvalue() )
===========
X6: construct
->: sink
<-: sink
X6: destroy
-----------
0/1 possible copies made
1/1 possible elisions performedNamed return value optimization (NRVO)
nrvo_source()
===========
->: nrvo_source
X7: construct
<-: nrvo_source
X7: destroy
-----------
0/1 possible copies made
1/1 possible elisions performedUnnamed return value optimization (URVO)
urvo_source()
===========
->: urvo_source
X8: construct
<-: urvo_source
X8: destroy
-----------
0/1 possible copies made
1/1 possible elisions performedReturn value used as ctor arg
X a(urvo_source())
===========
->: urvo_source
X9: construct
<-: urvo_source
X9: destroy
-----------
0/2 possible copies made
2/2 possible elisions performedReturn rvalue passed by value
identity( rvalue() )
===========
X10: construct
->: identity
X11: <- X10: **copy**
<-: identity
X11: destroy
X10: destroy
-----------
1/2 possible copies made
1/2 possible elisions performed*** 1 possible elisions missed! ***
X0: destroy

C++编译器优化:Copy Elision(省略不必要的拷贝)相关推荐

  1. 一道面试题:你了解哪些编译器优化行为?知道Copy elision 、RVO吗?

    C++11以后,g++ 编译器默认开启复制省略(copy elision)选项,可以在以值语义传递对象时避免触发复制.移动构造函数.copy elision 主要发生在两个场景: 函数返回的是值语义时 ...

  2. c++的复制省略(copy elision)

    学习 A simple C++11 Thread Pool 时,发现函数返回了std::future,而std::future的拷贝构造和拷贝赋值都是delete的,感觉有点怪,查了一下,看到 编译器 ...

  3. C++ 的复制省略(copy elision)特性

    C++复制省略的介绍: https://zh.wikipedia.org/wiki/%E5%A4%8D%E5%88%B6%E7%9C%81%E7%95%A5 一个有趣的例子: class Test { ...

  4. 浅谈C++11标准中的复制省略(copy elision,也叫RVO返回值优化)

    严正声明:本文系作者davidhopper原创,未经许可,不得转载. C++11以及之后的C++14.17标准均提出一项编译优化技术:复制省略(copy elision,也称复制消除),另外还有RVO ...

  5. C++构造与析构(12) - copy elision编译器优化

    目录 1.copy elision说明 2.优化分析 3.如何关闭优化 1.copy elision说明 Copy elision (或Copy omission)是一项编译器优化技术,用于避免不必要 ...

  6. C++17之省略不必要的拷贝Copy Elision

    从C++发展历史看来,c++ 17引入了一个规则,要求在满足一定的条件下避免对象的复制,这在以前是可选的.C++17中一个叫做强制复制省略的技术就是基于这个观点的. 至少包括以下两项内容: 1. 返回 ...

  7. C++编程法则365条一天一条(358)copy elision(返回值优化NVO和具名返回值优化NRVO)

    文章目录 强制编译器实现的优化 非强制实现优化 参考:https://en.cppreference.com/w/cpp/language/copy_elision Elision 是省略.删节或者忽 ...

  8. C++ Copy Elision

    故事得从 copy/move constructor 说起: The default constructor (12.1), copy constructor and copy assignment ...

  9. 有保证的复制消除(Guaranteed Copy Elision)

    作者:Jonas Devlieghere 原文地址:https://jonasdevlieghere.com/guaranteed-copy-elision/ 新的 C++ 17 标准带来了很多令人兴 ...

  10. Copy Elision

    最近写程序的时候突然意识到了一个(也许大多数人早就意识到的)很常见的问题.我们知道复制一个对象(尤其是复杂的对象/实例)往往需要不小的计算开销(更别提复制一个数组的对象了).但另一方面,复杂对象(群) ...

最新文章

  1. Servlet学习-request
  2. POJ - 1185 炮兵阵地(状压dp)
  3. Python练习-迭代器-模拟cat|grep文件
  4. Oracle if else if for case
  5. html加入购物车的动画,vue实现加入购物车动画
  6. 宁波政务云资源的介绍与申请
  7. AWS再迎大师加盟:Java之父James Gosling决定效力
  8. 基于 Spring 实现管道模式的最佳实践
  9. 运行TensorFlow
  10. 关于final、finally、finalize
  11. 一根烟上热搜,先让 AI 看看你的肺
  12. 04 bbed修复system文件头损坏
  13. postgres建表
  14. 正确使用SqlConnection对象,兼谈数据库连接池
  15. 正则表达式(三)操作符的运算优先级、全部符号的解释
  16. python建模与仿真控制系统_系统建模与仿真
  17. Qt编写/注册/使用activex控件
  18. 微信小程序影视评论交流平台系统毕业设计毕设(6)开题答辩PPT
  19. 青少年CTF wp合集
  20. linux操作系统是著名的分布式系统,紫光展锐操作系统生态覆盖 Android、Linux、RTOS,面向分布式、智能化...

热门文章

  1. 【转】未连接到互联网的解决方法(chrome)
  2. 在虚拟机中开启VT功能
  3. mysql存密码_存储用户ID和密码到mysql数据库的方法
  4. Java线程生命周期与状态切换
  5. 金典《歌手》2019即将首播 创作季上演神仙打架
  6. 解析mac苹果电脑与Windows电脑的区别
  7. python告诉你ti8 dota2英雄bp
  8. 抖音国庆小游戏是如何实现的?带你走近 Cocos
  9. 关于星巴克推广活动的实验测试
  10. onload 属性的作用