模板与c++11--右值引用
函数参数传递
struct huge_data{
char *content;
unsigned sz;
huge_data():content(),sz(){
cout<<this<<"->huge_data()"<<endl;
}
huge_data(unsigned sz):content(new char[sz]),sz(sz){
cout<<this<<"->huge_data("<<sz<<")"<<endl;
}
huge_data(huge_data const &h):content(new char[h.sz]),sz(h.sz){
copy(h.content,h.content+sz,content);
cout<<this<<"->huge_data("<<&h<<")"<<endl;
}
huge_data &operator=(huge_data const &h){
if(&h == this) return *this;
if(content) delete[] content;
content = new char[h.sz];
copy(h.content,h.content+sz,content);
sz = h.sz;
cout<<this<<"->operator=("<<&h<<")"<<endl;
return *this;
}
~huge_data(){
if(content){
delete[] content;
}
}
};
huge_data prepare_data(unsigned sz){
huge_data h(sz);
memset(h.content,'a',sizeof(char)*sz);
return h;
}
class BFS{
public:
void test(){
cout<<"begin"<<endl;
huge_data a;
a = prepare_data();
cout<<"end"<<endl;
}
};
参数传递的详细步骤:
1,在test函数的call back上预留能保存huge_data实例的空间,并将其地址作为prepare_data的参数传递到调用栈
2,prepare_data调用huge_data的构造函数为其局部变量h创建huge_data的实例,在函数返回时将h的内容copy构造到test函数的预留空间中
3,test函数再调用赋值操作符=从值从预留空间赋值到a上并释放预留空间
在编译取消优化选项g++ -fno-elide-constructors test.cpp
begin
0x7ffecce0c7f0->huge_data()
0x7ffecce0c7b0->huge_data()
0x7ffecce0c800->huge_data(0x7ffecce0c7b0)
0x7ffecce0c7f0->operator=(0x7ffecce0c800)
end Process returned (0x0) execution time : 0.003 s
Press ENTER to continue.
如果使用编译优化选项的话,就是编译时去掉-fno-elide-constructors
begin
0x7ffd15fa0db0->huge_data()
0x7ffd15fa0dc0->huge_data()
0x7ffd15fa0db0->operator=(0x7ffd15fa0dc0)
end
可以看到省略了一次copy构造函数的调用,
-fno-elide-constructors- The C++ standard allows an implementation to omit creating a temporary which is only used to initialize another object of the same type. Specifying this option disables that optimization, and forces G++ to call the copy constructor in all cases.
g++ 编译选项,no-elide-constructors,标准c++允许这样的机制,当被用来初始化另一个相同类型的另外对象时,省略产生临时变量。如果 指定了-fno-elide-constructors选项,可以禁止此项优化,强制使g++在所有的cases中调用copy constructor。
=========================================
左值,非左值
在c语言中可用于区分赋值和不可赋值的对象。左值可放在复制语句、等号左边的对象,也就是可以进行赋值的对象。常见的左值包括任何变量、指针去引用表达式,而典型的非左值由常数和函数调用。
int *pass(int *p) {return p;}
void main(){
int a,*p;
a = 1;
p = &a;//指针取引用表达式也是左值
1 = 2;//常量1不能进行复制,非左值
pass(p) = &a;//函数返回值也不是左值
*pass(p) = 1;//但是指针去引用后,还是左值
}
c++中左值的本质含义: B.Kernighan与D.Ritchie给出的,所谓对象是agiel具有名称的存储空间,1左值则是意味着某个对象的表达式。
就是说,如果表达式意指一个具名的存储空间,也就意味着随后这一存储空间中的内容还可以依据其名字而获取,则当前对该存储空间的值进行修改(如赋值),才可行。
非左值,1根本没有存储空间的数值,如各种常数,可能在编译时直接优化成指令中的常数而没有存储空间,显然其内容也无法修改。
2指某个无名存储空间的表达式(右值)。
=============
右值,指某个无名存储空间的表达式,如果某个存储空间无名,意味着现在修改了其中的内容,也无法找到该空间再提取其内容,以前的c++标准是禁止修改右值中的内容。
但是在c++11引入右值引用后,是可以的。
某一类型的右值引用类型写为T&&,原有引用类型T&表示左值引用。
====什么情况可以使用右值引用?
右值引用赋予了我们更改右值内容的权利,如左值引用类型一样,右值引用类型可用于函数参数,也可以声明局部变量。
=====移动构造与移动复制
模板与c++11--右值引用的更多相关文章
- [c++11]右值引用、移动语义和完美转发
c++中引入了右值引用和移动语义,可以避免无谓的复制,提高程序性能.有点难理解,于是花时间整理一下自己的理解. 左值.右值 C++中所有的值都必然属于左值.右值二者之一.左值是指表达式结束后依然存在的 ...
- C++11右值引用
[C++11右值引用] 1.什么是左值?什么是右值? 左值是表达式结束后依然存在的对象:右值是表达式结束时就不再存在的对象. 2.std::move的作用是什么? std::move用于把任意类型转化 ...
- 关于C++11右值引用和移动语义的探究
关于C++11右值引用和移动语义的探究
- c++11——右值引用
1. 左值和右值 左值是表达式结束之后仍然存在的持久化对象,而右值是指表达式结束时就不再存在的临时对象. c++11中,右值分为两种类型:将亡值(xvalue, expiring value) ...
- C++ 11 右值引用
C++11中引入的一个非常重要的概念就是右值引用.理解右值引用是学习“移动语义”(move semantics)的基础.而要理解右值引用,就必须先区分左值与右值. 注意:左值右值翻译可能有些问题 *L ...
- C++ 11 右值引用以及std::move
转载请注明出处:http://blog.csdn.net/luotuo44/article/details/46779063 新类型: int和int&是什么?都是类型.int是整数类型,in ...
- 【转】C++ 11 右值引用的理解
右值引用的目的之一,是为了C++中一个比较影响性能的问题:拷贝临时对象,例如,在 int foo(){ ... } int x; x = foo(); 中,在第三句中,发生了以下的事情: 1.销毁 x ...
- C++11右值引用和std::move语句实例解析
关键字:C++11,右值引用,rvalue,std::move,VS 2015 OS:Windows 10 右值引用(及其支持的Move语意和完美转发)是C++0x将要加入的最重大语言特性之一.从实践 ...
- C++11 右值引用和转移语义
新特性的目的 右值引用 (Rvalue Referene) 是 C++ 新标准 (C++11, 11 代表 2011 年 ) 中引入的新特性 , 它实现了转移语义 (Move Sementics) 和 ...
- C++11 右值引用 与 转移语义
新特性的目的 右值引用(R-value Reference)是C++新标准(C++11, 11代表2011年)中引入的新特性,它实现了转移语义(Move Semantics)和精确传递(Perfect ...
随机推荐
- JS中的Global对象
Global对象可以说是ECMAScript中最特别的一个对象了.因为不管你从什么角度上看,这个对象都是不存在的.ECMAScript中的Global对象在某种意义上是作为一个终极的“兜底儿对象”来定 ...
- IOS 绘制条纹背景
@interface NJViewController () @property (weak, nonatomic) IBOutlet UITextView *contentView; - (IBAc ...
- ORACLE的raw属性
网上说RAW类型在网络数据传送的时候可以避免字节的字符集转换,在mssql中使用的GUID类型在oracle中对应的也是raw类型(一般是raw(16)),如果此时使用连接查询将raw类型的字段和va ...
- POJ 1703 Find them, Catch them(并查集,等价关系)
DisjointSet保存的是等价关系,对于某个人X,设置两个变量Xa,Xb.Xa表示X属于a帮派,Xb类似. 如果X和Y不是同一个帮派,那么Xa -> Yb,Yb -> Xa... (X ...
- python_70_内置函数2
#hex() 转16进制 oct()转8进制 print(hex(255)) print(oct(10)) #id() 返回内存地址 print(id('a')) ''' isinstance(obj ...
- Luogu P1471 方差
题目传送门 开了十倍空间才过是什么鬼?该不会我线段树炸了吧-- 细思极恐 平均数都会求,维护区间和,到时候除一下就好了. 方差的求法如下 (用的Luogu的图片) 因为要维护一个平方,我们可以考虑使用 ...
- CUDA入门需要知道的东西
CUDA刚学习不久,做毕业要用,也没时间研究太多的东西,我的博客里有一些我自己看过的东西,不敢保证都特别有用,但是至少对刚入门的朋友或多或少希望对大家有一点帮助吧,若果你是大牛请指针不对的地方,如果你 ...
- 对于无法激活的系统—使用rearm命令延长试用期
1.首先安装后,有一个30天的使用期. 2.在30天试用期即将结束时,用rearm命令后重启电脑,剩余时间又回复到30天.微软官方文档中声明该命令只能重复使用3次,也说是说总共可以免费体验120天. ...
- 避免修改Android.mk添加cpp文件路径
手工输入项目需要编译的cpp文件到Android.mk里的缺点 1)繁琐,如果cpp文件很多,简直无法忍受 2)手工输入过程中容易出现错误 3)如果cpp文件更改名称,需要修改android.mk文件 ...
- c#基础之循环探索
前言在学习基础的语法中循环控制是程序语句控制中的一种,循环在很多的操作中都有应用,例如在获得数据库中的查询的数据之后可以用循环遍历的方式拿到每一行的数据,从而拿到每一个单元格的数据,在文件的操作中也大 ...