模板与c++11--右值引用
2016-05-31 13:51
447 查看
函数参数传递
参数传递的详细步骤:
1,在test函数的call back上预留能保存huge_data实例的空间,并将其地址作为prepare_data的参数传递到调用栈
2,prepare_data调用huge_data的构造函数为其局部变量h创建huge_data的实例,在函数返回时将h的内容copy构造到test函数的预留空间中
3,test函数再调用赋值操作符=从值从预留空间赋值到a上并释放预留空间
在编译取消优化选项g++
如果使用编译优化选项的话,就是编译时去掉
可以看到省略了一次copy构造函数的调用,
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&表示左值引用。
====什么情况可以使用右值引用?
右值引用赋予了我们更改右值内容的权利,如左值引用类型一样,右值引用类型可用于函数参数,也可以声明局部变量。
=====移动构造与移动复制
struct huge_data{ char *content; unsigned sz; huge_data():content(0),sz(0){ 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(1024); 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(1024) 0x7ffecce0c800->huge_data(0x7ffecce0c7b0) 0x7ffecce0c7f0->operator=(0x7ffecce0c800) end Process returned 0 (0x0) execution time : 0.003 s Press ENTER to continue.
如果使用编译优化选项的话,就是编译时去掉
-fno-elide-constructors
begin 0x7ffd15fa0db0->huge_data() 0x7ffd15fa0dc0->huge_data(1024) 0x7ffd15fa0db0->operator=(0x7ffd15fa0dc0) end
可以看到省略了一次copy构造函数的调用,
-fno-elide-constructorsThe 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++中placement new操作符(经典)
- 第十四周--stl阅读程序
- OC语言9-@property @synthesize和id
- unreal engine 4 BeginPlay,GEngine 还有其他一些东西找不到
- 第十四周--stl程序阅读
- OC语言8-点语法和变量作用域
- OC语言7—多态
- C++线程安全队列
- C++队列模板使用std::queue
- C++ Unicode与UTF_8 编码转换
- C语言 break跳出循环
- OC语言6—继承
- 让自己的C++程序(非服务程序)运行为一个windows service
- OC语言5—封装
- android studio 2.2 C++ 支持(CMAKE方法)
- OC语言4-内存管理
- C++移位运算符
- 2016从零开始纯C语言、C++语言一步一步完成RPG大型游戏开发
- C/C++struct与C++struct/class关键字详解
- 二路归并排序算法实现-完整C语言程序