1.绑定到一个将要销毁的右值的引用——移动

2.左值表达式——对象的身份;右值表达式——对象的值

int i=;
int& r=i; int&& rr=i;//×,左值不能绑定到右值引用
int& r2=i*;//×,右值不能绑定到左值引用 const int& r3=i*;//√,右值可以绑定const引用
int&& rr2 = i*;//右值绑定到右值引用 int&& rr1=;//√
int&& rr2=rr1;//× int&& rr3=std::move(rr1);//√,使用std可以避免潜在的命名冲突

3.左值持久,右值短暂(一般是字面常量,或表达式创建的临时对象(如上))//变量寿命很长的,出}才会被销毁

4.右值引用的对象即将被销毁且该对象没有其他用户

5.移动构造函数和移动赋值运算符

5.1 移动构造函数不分配任何新内存,直接接管给定的内存,接管后将原对象置为null

StrVec(StrVec&& s) noexcept :elements(s.elements), first_free(s.first_free), cap(s.cap)//接管s的资源
{
s.elements = s.first_free = s.cap = nullptr;//让s进入null,否则销毁s时,构造也会被销毁
}

5.2 移动赋值运算符

StrVec& operator=(StrVec&& rhs) noexcept//为何其他地方不需要?
{
if (this != &rhs)//检测自赋值
{
free();
elements = rhs.elements;
first_free = rhs.first_free;
cap = rhs.cap;
rhs.elements = rhs.first_free = rhs.cap = nullptr;
}
return *this;
}

5.3 合成移动操作:

  类定义了自己的拷贝构造函数、拷贝赋值运算符或析构函数,便不会合成移动构造函数和移动赋值运算符。只有当一个类未定义任何自己版本的拷贝控制成员,且类的每个非static数据成员都可以移动时,编译器才会为其合成移动构造函数或移动赋值运算符。

struct X{
int i; //内置类型,可以移动
string s;//string有定义的移动操作
}; struct hasX{
X men;//X有合成的移动操作
}; X x,x2=std::move(x);//使用合成移动构造函数
hasX hx,hx2=std::move(hx); //使用合成移动构造函数

5.4 定义了一个移动构造函数或移动赋值运算符的类,必须定义自己的拷贝操作。否则,这些成员将是delete的

6.移动右值,拷贝左值。但若没有移动构造函数,右值也被拷贝。

7.一个类有一个可用的拷贝构造函数,没有移动构造函数,则对象是通过拷贝构造函数来“移动”的。同理,适用于拷贝赋值运算符和移动赋值运算符。

class StrVec {
public:
StrVec() :elements(nullptr), first_free(nullptr), cap(nullptr) {}//默认初始化
StrVec(const StrVec&);//拷贝构造
StrVec& operator=(const StrVec&);//拷贝赋值运算符
~StrVec(); StrVec(StrVec&& s) noexcept :elements(s.elements), first_free(s.first_free), cap(s.cap)//接管s的资源
{
s.elements = s.first_free = s.cap = nullptr;//让s进入null
}
StrVec& operator=(StrVec&& rhs) noexcept
{
if (this != &rhs)//检测自赋值
{
free();
elements = rhs.elements;
first_free = rhs.first_free;
cap = rhs.cap;
rhs.elements = rhs.first_free = rhs.cap = nullptr;
}
return *this;
} void push_back(const string&);//拷贝元素
void push_back(string&&);//移动元素,右值引用
string* begin() const { return elements; }
string* end() const { return first_free; } size_t size() const { return first_free - elements; }
size_t capacity() const { return cap - elements; }
private:
static std::allocator<std::string> alloc;//分配器
void chk_n_alloc() { if (size() == capacity()) reallocate(); }//每一次添加元素都要check pair<string*, string*> alloc_n_copy(const string*, const string*);//工具,给拷贝构造、赋值运算符和析构用
void reallocate(); //获得更多内存并拷贝元素 void free(); //销毁释放内存 std::string *elements; //指向数组元素的指针
std::string *first_free; //指向第一个空闲元素的指针
std::string *cap; //指向数组尾后位置的指针
}; void StrVec::push_back(const string& s)
{
chk_n_alloc();//确保空间够容纳新的元素
alloc.construct(first_free++, s);
} void StrVec::push_back(string&& s)
{
chk_n_alloc();//确保空间够容纳新的元素
alloc.construct(first_free++, std::move(s));
} StrVec vec;
string s = "some thing";
vec.push_back(s);//调用push_back(const string& s)
vec.push_back("done");//调用push_back(string&& s)

8.左值和右值的引用成员函数

8.1 右值引用如何修饰成员函数,什么含义,怎么调用

class Foo
{
Foo& operator=(const Foo& rhs) &
{
//rhs赋值给本对象
return *this;//指向左值
}
Foo sorted() && ;
Foo sorted() const &;
private:
list<int> data;
};
Foo Foo::sorted() &&//本对象是右值,没有其他用户,可以对源对象排序
{
sort(data.begin(), data.end());
return *this;
}
Foo Foo::sorted() const &//本对象是左值,只能先复制一份,再排序,不能改变原来的
{
Foo ret(*this);
sort(ret.data.begin(), ret.data.end());
return ret;
}

8.2 定义两个或以上同名同参数列表的成员函数,要么都加上引用限定符,要么都不加

    Foo sorted() && ;//
Foo sorted() const &;//2都加(如果没有&就×)
using Comp = bool(const int&, const int&);//com是函数类型的类型别名
Foo sorted(Comp*);//
Foo sorted(Comp*) const;//4都不加(如果有&就×)

9.问题

virtual Quote* clone() && {return new Quote(std::move(*this));}
virtual shared_ptr<Quote> clone() const & { return make_shared<Quote>(*this); }

有了&&限定符,*this本身就是右值?为何还要std::move(*this)呢?不能return new Quote(*this)?这种函数什么时候用?

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

  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() 右值引用和右值的关系 完美转发 引用折叠推导 ...

  10. C++ 11 右值引用

    C++11中引入的一个非常重要的概念就是右值引用.理解右值引用是学习“移动语义”(move semantics)的基础.而要理解右值引用,就必须先区分左值与右值. 注意:左值右值翻译可能有些问题 *L ...

随机推荐

  1. Ajax的那点事

    Ajax中什么是同步.异步? 同步:就是用户填写完信息之后,全部提交给服务器,等待服务器的回应,是一次性全部的. 异步:当用户填写完一条信息之后,这条信息会自动向服务器提交,然后服务器响应客户端,在此 ...

  2. Html5 学习笔记 Sublime text3 和 Emmet 插件

    下载地址 :https://pan.baidu.com/s/1MpkaYdAcZd6RmPpmvOdK7w Emmet 压缩包 并且解压: 安装 Sublime Text 3, 选择首选项 浏览插件 ...

  3. Springboot03-异常处理

    springboot默认异常处理 Spring Boot提供了一个默认的映射:/error,当处理中抛出异常之后,会转到该请求中处理,并然后返回一个固定的错误页面 统一异常处理 创建全局异常处理类 @ ...

  4. WebSocket 网页聊天室

    先给大家开一个原始的websocket的连接使用范例 <?php /* * recv是从套接口接收数据,也就是拿过来,但是不知道是什么 * read是读取拿过来的数据,就是要知道recv过来的是 ...

  5. Robot Framework 执行结果无法查看(tomcat部署)

    打开jenkins系统管理-命令行执行: System.setProperty("hudson.model.DirectoryBrowserSupport.CSP","& ...

  6. WPF-将DataGrid控件中的数据导出到Excel

    原文:WPF-将DataGrid控件中的数据导出到Excel 导出至Excel是非常常见,我们可以用很多类库,例如Aspose.NOPI.Interop,在这里我们使用微软自家的工具.我的WPF绑定的 ...

  7. arcpy脚本使用多接图表图斑对对应多幅影像进行裁边处理

    插个广告,制作ArcGIS的Tool工具学习下面的教程就对了: 零基础学习Python制作ArcGIS自定义工具观看链接 <零基础学习Python制作ArcGIS自定义工具>课程简介 先将 ...

  8. db2备份与恢复

    备份数据库: 离线备份 1.连接至数据库: db2 connect to test user db2admin using db2admin 2.显示数据库应用状态 db2 list applicat ...

  9. 自定义checkbox(对勾)和radio样式

    checkbox: html: <div> <label class="unSelected selected" for="choose"&g ...

  10. 第十一章 存储之ConfigMap

    1.描述信息 ConfigMap 功能在 Kubernetes1.2 版本中引入,许多应用程序会从配置文件.命令行参数或环境变量中读取配置信息.ConfigMap API 给我们提供了向容器中注入配置 ...