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

由于右值所产生的临时变量问题一直是一种诟病,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. (2.9)Mysql之SQL基础——索引的查看与删除

    (2.9)Mysql之SQL基础——索引的查看与删除 关键词:mysql索引查看,mysql索引删除 1.索引查询(以下包括主键,唯一,普通,复合,全文,但不包括外键) (1)按库查询 select ...

  2. 查看MySQL锁定情况

    SHOW STATUS LIKE '%Table_locks%' Table_locks_immediate | 105         | Table_locks_waited   | 3      ...

  3. MySQL5.7多源复制

    MySQL5.7开始支持多源复制,也就是多主一从的复制架构: 使用多源复制的考虑: 1.灾备作用:将各个库汇总在一起,就算是其他库都挂了(整个机房都无法连接了),还有最后一个救命稻草: 2.备份:直接 ...

  4. mysql++使用

    Mysql++是官方发布的.一个为MySQL设计的C++语言的API.Mysql++为Mysql的C-Api的再次封装,它用STL(Standard Template Language)开发并编写,并 ...

  5. node学习笔记第一天

    ES6---* JavaScript语言随着使用的人越来越多,ECMA语法规范:if/else* 为了让js语言更适应大型应用的开发.旨在消除一些怪异的行为 ### 包含内容(strict严格模式)- ...

  6. 【spring-boot】 springboot整合quartz实现定时任务

    在做项目时有时候会有定时器任务的功能,比如某某时间应该做什么,多少秒应该怎么样之类的. spring支持多种定时任务的实现.我们来介绍下使用spring的定时器和使用quartz定时器 1.我们使用s ...

  7. Cannot perform runtime binding on a null reference

    一个方法的参数是dynamic  obj 方法内调用了obj.Header 但是外部传递进来的obj是null,然后就会报这个错.

  8. luogu p3371 单源最短路径(dijkstral

    本来我写的对的 我就多手写了个 ios::sync_with_stdio(false); 我程序里面用了cin 还有scanf 本来想偷偷懒 我就说 我查了半天错 根本找不到的啊... 后来交了几次 ...

  9. 使用向量化的 if:ifelse

    进行分支计算的一个替代方法是 ifelse( ).这个函数接收一个逻辑向量作为判定条件,并且返回一个向量.对于逻辑判定条件内的每一个元素,若是 TRUE,则选择第 2个参数 yes 中所对应的元素:若 ...

  10. 递归--练习10--noi1696逆波兰表达式

    递归--练习10--noi1696逆波兰表达式 一.心得 递归大法好 二.题目 1696:逆波兰表达式 总时间限制:  1000ms 内存限制:  65536kB 描述 逆波兰表达式是一种把运算符前置 ...