版权声明:本文为博主原创文章,未经博主允许不得转载。

由于右值所产生的临时变量问题一直是一种诟病,C++11中引入了右值引用这个核心语言机制,来提升运行期性能.

首先我先说明一下什么是左值和右值: 左值和右值都是针对表达式而言的,左值是指表达式结束后依然存在的持久对象,右值是指表达式结束时就不再存在的临时对象

int b = ;   //这里b是左值 20是右值 ,因为这个表达式过后 20将不存在了  而b依然存在
//同时也可以根据能否取地址来判断是否是左值(能取地址)还是右值(不能取地址),如本例中 20不能取地址顾为右值

右值引用一般都用&&来修饰

下面我们来证实一下上面的右值判断

#include <iostream>
#include <vector> using namespace std; void process(int& i)//右值引用
{
cout << "process(int&): " << i << endl;
}
void process(int&& i)//左值引用
{
cout << "process(int&&): " << i << endl;
}
void forward(int&& i)//中间函数
{
cout << "forward(int&&): " << i << ", ";
process(i);
// process(std::forward<int>(i));
} int main(int argc, const char * argv[]) { int a = ; process(a); process(); forward(); //不完美的转交 右值传递后 却调用左值 原因转交过程中转变成一个named obj forward(move(a));//强制转换为右值 也不好用 std::move()强制转换为右值引用 return ;
}

输出结果

是不是发现了调用中间函数的时候丢了什么,把右值引用丢了.使用std::forward<T>()可以避免这种现象(上面的注释部分).


下面我们开始研究一下move()

move(),其实类似于浅拷贝,也可以理解成"偷"

下面我们来实现一个带右值引用的类


这个是不带右值引用的

#include <iostream>
#include <vector> using namespace std; class Person
{ private:
int _age;
char* _name;
size_t _len;
void _test_name(const char *s)
{
_name = new char[_len+];
memcpy(_name, s, _len);
_name[_len] = '\0';
} public:
//default ctor
Person(): _age() , _name(NULL), _len(){cout<<"default cotr"<< endl;} Person(const int age, const char * p) : _age(age), _len(strlen(p)) {
_test_name(p);
cout<<"cotr"<<endl;
} //dctor
~Person(){
if(_name){
delete _name;
}
cout<<"default dctor"<<endl;
} // copy ctor
Person (const Person& p):_age(p._age),_len(p._len){
_test_name(p._name);
cout<<"copy ctor"<<endl;} //copy assignment
Person & operator=(const Person& p)
{
if (this != &p){
if(_name) delete _name;
_len = p._len;
_age = p._age;
_test_name(p._name);
}
else{
cout<< "self Assignment. Nothing to do." <<endl;
}
cout<<"copy assignment"<<endl;
return *this;
}
}; int main(int argc, const char * argv[]) { Person * obj = new Person(); vector<Person> v1; v1.push_back(*obj); delete obj;
return ;
}

输出结果


带右值引用的

#include <iostream>
#include <vector> using namespace std; class Person
{ private:
int _age;
char* _name;
size_t _len;
void _test_name(const char *s)
{
_name = new char[_len+];
memcpy(_name, s, _len);
_name[_len] = '\0';
} public:
//default ctor
Person(): _age() , _name(NULL), _len(){cout<<"default cotr"<< endl;} Person(const int age, const char * p) : _age(age), _len(strlen(p)) {
_test_name(p);
cout<<"cotr"<<endl;
} //dctor
~Person(){
if(_name){
delete _name;
}
cout<<"default dctor"<<endl;
} // copy ctor
Person (const Person& p):_age(p._age),_len(p._len){
_test_name(p._name);
cout<<"copy ctor"<<endl;} //copy assignment
Person & operator=(const Person& p)
{
if (this != &p){
if(_name) delete _name;
_len = p._len;
_age = p._age;
_test_name(p._name);
}
else{
cout<< "self Assignment. Nothing to do." <<endl;
}
cout<<"copy assignment"<<endl;
return *this;
} // move cotr , wihth "noexcept"
Person(Person&& p) noexcept :_age(p._age) , _name(p._name), _len(p._len){
cout<<"move ctor"<<endl;
p._age = ;
p._name = NULL;//必须为NULL 如果你把这里设为空 那么这个函数走完之后将调用析够函数 因为当前的Person类 和你将要析够的Person的_name指向同一部分 析构部分见析构函数
}
// move assignment
Person& operator=(Person&& p) noexcept { if (this != &p)
{
if(_name) delete _name;
_age = p._age;
_len = p._len;
_name = p._name;
p._age = ;
p._len = ;
p._name = NULL;
}
cout<<"move assignment"<<endl;
return *this;
}
}; int main(int argc, const char * argv[]) { Person * obj = new Person(); vector<Person> v1; v1.push_back(move(*obj)); delete obj;
return ;
}

输出结果

可以见到少调用一次构造函数.以上就是右值引用的简单实现了.

参照<<侯捷 C++新标准 C++11>>

C++11_ 右值引用的更多相关文章

  1. C++右值引用浅析

    一直想试着把自己理解和学习到的右值引用相关的技术细节整理并分享出来,希望能够对感兴趣的朋友提供帮助. 右值引用是C++11标准中新增的一个特性.右值引用允许程序员可以忽略逻辑上不需要的拷贝:而且还可以 ...

  2. C++ 11 中的右值引用

    C++ 11 中的右值引用 右值引用的功能 首先,我并不介绍什么是右值引用,而是以一个例子里来介绍一下右值引用的功能: #include <iostream>    #include &l ...

  3. 图说函数模板右值引用参数(T&&)类型推导规则(C++11)

    见下图: 规律总结: 只要我们传递一个基本类型是A④的左值,那么,传递后,T的类型就是A&,形参在函数体中的类型就是A&. 只要我们传递一个基本类型是A的右值,那么,传递后,T的类型就 ...

  4. c++11的右值引用、移动语义

    对于c++11来说移动语义是一个重要的概念,一直以来我对这个概念都似懂非懂.最近翻翻资料感觉突然开窍,因此记下.其实搞懂之后就会发现这个概念很简单,并无什么高深的地方. 先说说右值引用.右值一般指的是 ...

  5. VS2012 error C2664: “std::make_pair”:无法将左值绑定到右值引用

    在vs2012(c++)make_pair()改动: C++: template <class T1, class T2> pair<V1, V2> make_pair(T1& ...

  6. 右值引用、move与move constructor

    http://blog.chinaunix.net/uid-20726254-id-3486721.htm 这个绝对是新增的top特性,篇幅非常多.看着就有点费劲,总结更费劲. 原来的标准当中,参数与 ...

  7. 【转】C++11 标准新特性: 右值引用与转移语义

    VS2013出来了,对于C++来说,最大的改变莫过于对于C++11新特性的支持,在网上搜了一下C++11的介绍,发现这篇文章非常不错,分享给大家同时自己作为存档. 原文地址:http://www.ib ...

  8. move语义和右值引用

    C++11支持move语义,用以避免非必要拷贝和临时对象. 具体内容见收藏中的“C++右值引用” .

  9. [转载] C++11中的右值引用

    C++11中的右值引用 May 18, 2015 移动构造函数 C++98中的左值和右值 C++11右值引用和移动语义 强制移动语义std::move() 右值引用和右值的关系 完美转发 引用折叠推导 ...

随机推荐

  1. JQuery的Ajax跨域请求的解决方式

            今天在项目中须要做远程数据载入并渲染页面,直到开发阶段才意识到ajax跨域请求的问题,隐约记得Jquery有提过一个ajax跨域请求的解决方式,于是即刻翻出Jquery的API出来研究 ...

  2. Centos安装自定义布局才能自己划分各个区的大小ctrl+z ,fg ,route -n ,cat !$ ,!cat ,XShell 设置, ifconfig CentOS远程连接 Linux中的输入流 第一节课

    Centos安装自定义布局才能自己划分各个区的大小ctrl+z ,fg ,route -n ,cat !$ ,!cat ,XShell 设置, ifconfig  CentOS远程连接  Linux中 ...

  3. PHP之设计模式

    https://blog.csdn.net/self_realian/article/details/78228733 掌握PHP各类设计模式,具备设计纯面向对象框架和系统能力是非常有必要的.给大家一 ...

  4. CentOS7.0安装Nginx 1.10.0

    首先由于nginx的一些模块依赖一些lib库,所以在安装nginx之前,必须先安装这些lib库,这些依赖库主要有g++.gcc.openssl-devel.pcre-devel和zlib-devel ...

  5. VS2010/MFC编程入门之十二(对话框:非模态对话框的创建及显示)

    上一节鸡啄米讲了模态对话框及其弹出过程,本节接着讲另一种对话框--非模态对话框的创建及显示. 鸡啄米已经说过,非模态对话框显示后,程序其他窗口仍能正常运行,可以响应用户输入,还可以相互切换.鸡啄米会将 ...

  6. 32Sql数据库的插入

    上一节讲了数据库的连接,本例直接将数据库的插入操作,重点还是QSqlQuery类 QSqlQuery query; //新建二维表 query.exec("CREATE TABLE stud ...

  7. MySQL从删库到跑路(二)——MySQL字符集与乱码解析

    作者:天山老妖S 链接:http://blog.51cto.com/9291927 一.字符集与编码 1.字符集简介 字符(Character)是各种文字和符号的总称,包括各国家文字.标点符号.图形符 ...

  8. python ConfigParser读取配置文件,及解决报错(去掉BOM)ConfigParser.MissingSectionHeaderError: File contains no section headers的方法

    先说一下在读取配置文件时报错的问题--ConfigParser.MissingSectionHeaderError: File contains no section headers 问题描述: 在练 ...

  9. 打开 EXCEL时出现RUN-TIME ERROR“91”,怎么解决?

    方法一: 开始—程序—microsoft—打开“windows office 2007 简易设置”,把“使用 office 03样式经典菜单”前的“√”去掉就OK了 方法二: 1. 打开注册表编辑器. ...

  10. c++第二十八天

    p140~p144:逗号运算符1.特点:1)规定运算顺序,即由左向右.2)逗号运算符的真正结果是右侧表达式的值! 练习 4.31 使用后置的运算符会有额外的内存开销, 在这道题中使用前置和后置结果貌似 ...