copy elison & RVO & NRVO
To summarize, RVO is a compiler optimization technique, while std::move is just an rvalue cast, which also instructs the compiler that it's eligible to move the object. The price of moving is lower than copying but higher than RVO, so never apply std::move to local objects if they would otherwise be eligible for the RVO.
因此,在能够使用copy elision时,我们不要在return时加std::move()。在copy elision不work时,我们还是要加上std::move()从而调用move constructor而不是调用copy constructor.
博文中比较费解的是最后一个示例,这么写似乎产生了bug。
个人理解:最后一个示例触发了RVO,导致第一次拷贝:栈内变量拷贝至返回值临时变量被省略(两次拷贝参见下文),第二次拷贝:临时变量拷贝至具名变量未省略。而因为变量类型是右值引用,第二次的拷贝变成了移动构造。于是就出现了奇怪的输出。
Copy elision
In general, the C++ standard allows a compiler to perform any optimization, provided the resulting executable exhibits the same observable behaviour as if (i.e. pretending) all the requirements of the standard have been fulfilled. This is commonly referred to as the "as-if rule".[8] The term return value optimization refers to a special clause in the C++ standard that goes even further than the "as-if" rule: an implementation may omit a copy operation resulting from a return statement, even if the copy constructor has side effects.[1]
The following example demonstrates a scenario where the implementation may eliminate one or both of the copies being made, even if the copy constructor has a visible side effect (printing text).[1] The first copy that may be eliminated is the one where a nameless temporary C
could be copied into the function f
's return value. The second copy that may be eliminated is the copy of the temporary object returned by f
to obj
.
#include <iostream> struct C {
C() {}
C(const C&) { std::cout << "A copy was made.\n"; }
}; C f() {
return C();
} int main() {
std::cout << "Hello World!\n";
C obj = f();
return ;
}
Depending upon the compiler, and that compiler's settings, the resulting program may display any of the following outputs:
Hello World!
A copy was made.
A copy was made.
Hello World!
A copy was made.
Hello World!
这里有一篇博文,结合了《深度探索C++对象模型》,博文链接。
在g++中开启选项-fno-elide-constructors可以去掉任何返回值优化,则C obj = f(); 中,会发生两次拷贝,f()内栈内变量拷贝构造返回值临时变量,返回值临时变量拷贝构造obj变量。
这里有一份更详细点的文档...
https://en.cppreference.com/w/cpp/language/copy_elision
===============================================================
最后是关于push_back与emplace_back的测试。
T &&var1 = std::move(var2); 不存在移动拷贝。
void emplace_back( Args&&... args );通过std::forward<Args>(args)...实现。
#include <bits/stdc++.h>
using namespace std;
struct Stu {
int age;
Stu(const int age = ):age(age) {
cout << "construct" << endl;
}
Stu(const Stu& s){
cout << "copy construct" << endl;
}
Stu(Stu&& s) {
cout << "move construct" << endl;
};
Stu& operator = (const Stu& s) {
cout << "operator construct" << endl;
}
~Stu(){
cout << "destruct" << endl;
}
}; Stu Init(const int age) {
return Stu(age);
} int main() {
Stu s1();
cout << "1--------------" << endl;
Stu s2 = Init();
cout << "2--------------" << endl;
vector<Stu> ve;
ve.reserve();
cout << "3--------------" << endl;
ve.push_back(s1);
cout << "4--------------" << endl;
Stu&& ss = std::move(s1);
ve.push_back(std::move(s1));
cout << "5--------------" << endl;
ve.emplace_back(Stu());
cout << "6--------------" << endl;
ve.emplace_back();
return ;
} /*
construct
1--------------
construct
move construct
destruct
move construct
destruct
2--------------
3--------------
copy construct
4--------------
move construct
5--------------
construct
move construct
destruct
6--------------
construct
destruct
destruct
destruct
destruct
destruct
destruct
*/
copy elison & RVO & NRVO的更多相关文章
- C++基础知识--DAY4
今天主要讲的是类中除了构造器析构器以外的拷贝构造器,运算符重载等问题 首先是拷贝构造器 1. copy constructor(拷贝构造) 其也是构造器,其地位和constructor的地位是一样的 ...
- 第15课 右值引用(2)_std::move和移动语义
1. std::move (1)std::move的原型 template<typename T> typename remove_reference<T>::type& ...
- [c++11]右值引用、移动语义和完美转发
c++中引入了右值引用和移动语义,可以避免无谓的复制,提高程序性能.有点难理解,于是花时间整理一下自己的理解. 左值.右值 C++中所有的值都必然属于左值.右值二者之一.左值是指表达式结束后依然存在的 ...
- [转][c++11]我理解的右值引用、移动语义和完美转发
c++中引入了右值引用和移动语义,可以避免无谓的复制,提高程序性能.有点难理解,于是花时间整理一下自己的理解. 左值.右值 C++中所有的值都必然属于左值.右值二者之一.左值是指表达式结束后依然存在的 ...
- HEC-ResSim原文档
HEC-ResSim Reservoir System Simulation User's Manual Version 3.1 May 201 ...
- RVO和NRVO
返回值优化(Return Value Optimization,简称RVO),是这么一种优化机制:当函数需要返回一个对象的时候,如果自己创建一个临时对象用户返回,那么这个临时对象会消耗一个构造函数(C ...
- C++编译器优化技术:RVO、NRVO和复制省略
现代编译器缺省会使用RVO(return value optimization,返回值优化).NRVO(named return value optimization.命名返回值优化)和复制省略(Co ...
- C++中返回对象的情形及RVO
http://www.cnblogs.com/xkfz007/archive/2012/07/21/2602110.html 之前有文章介绍过临时对象和返回值优化RVO方面的问题.见此处. 在C++中 ...
- c++ rvo vs std::move
c++ rvo vs std::move To summarize, RVO is a compiler optimization technique, while std::move is just ...
随机推荐
- [清华集训2017]榕树之心[树dp]
题意 题目链接 分析 首先解决 \(subtask3\) ,我们的策略就是进入子树,然后用其它子树来抵消,注意在子树内还可以抵消. 可以转化为此模型:有一个数列 \(a\) ,每次我们可以选定两个值 ...
- R绘图 第七篇:绘制条形图(ggplot2)
使用geom_bar()函数绘制条形图,条形图的高度通常表示两种情况之一:每组中的数据的个数,或数据框中列的值,高度表示的含义是由geom_bar()函数的参数stat决定的,stat在geom_ba ...
- 生活沉思录 via 哲理小故事(一)
1.小托蒂的悲剧 意大利小男孩托蒂,有一只十分奇怪的眼睛,因为从生理上看,这是一只完全正常的眼睛,但却是失明的. 原来,托蒂刚出生时,这只眼睛轻度感染,曾用绷带缠了两个星期.这对常人来说几乎没有人任何 ...
- 几何学观止(Riemann流形部分)
上承这个页面,相较之前,增加了古典的曲线曲面论,这部分介绍得很扼要,Riemann流形介绍得也很快,花了仅仅30页就介绍到了Gauss-Bonnet公式.同时配上了提示完整的习题. 几何学观止-Rie ...
- python-编码-15
ascii A : 00000010 8位 一个字节 unicode A : 00000000 00000001 00000010 00000100 32位 四个字节 中:00000000 00000 ...
- Python-复习-习题-13
复习 dict: dic = {'name':'alex'}增:dic['age'] = 21 存在就覆盖dic.setdefault() 存在什么也不做,没有就增加 删除:pop()按照key删除, ...
- combox的基本应用
easyui-combox:控件的初始化: 可以在其中进行文字的筛选功能(过滤), 动态加载数据的方法. <!DOCTYPE html><html lang="en&quo ...
- 《Linux内核分析与实现》 第五周 读书笔记
第3章 进程管理 20135307张嘉琪 3.1 进程 进程就是处于执行期的程序(目标码存放在某种存储介质上),但进程并不仅仅局限于一段可执行程序代码.通常进程还要包含其他资源,像打开的文件,挂起的信 ...
- 自定义视图(SpringMVC)
一.首先理解视图的解析过程 1)请求处理方法执行完成后,最终返回一个 ModelAndView 对象. ModelAndView 对象,它包含了逻辑名(访问URL)和模型对象(javaBean数据)的 ...
- C#改变图片大小
今天一女同事要做一个改变图片大小的功能,然后我就手写了几行代码,以后可能用得上 byte[] buffer = new byte[1]; //Byte转为Image对象 MemoryStream ms ...