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. 洛谷P4169 [Violet]天使玩偶/SJY摆棋子(CDQ分治)

    [Violet]天使玩偶/SJY摆棋子 题目传送门 解题思路 用CDQ分治开了氧气跑过. 将输入给的顺序作为第一维的时间,x为第二维,y为第三维.对于距离一个询问(ax,ay),将询问分为四块,左上, ...

  2. PAT_A1085#Perfect Sequence

    Source: PAT A1085 Perfect Sequence (25 分) Description: Given a sequence of positive integers and ano ...

  3. Linux vsftpd服务配置以及三种验证方式以及常见错误解决办法

    文件传输协议(FTP): 文件传输协议(FTP,File Transfer Protocol),即能够让用户在互联网中上传.下载文件的文件协议,而FTP服务器就是支持FTP传输协议的主机,要想完成文件 ...

  4. 关于html 修改滚动条的问题

    之前项目需要改变滚动条的样式 一.修改原生样式 原文地址:https://blog.csdn.net/zh_rey/article/details/72473284 问题在于无法兼容火狐与ie等浏览器 ...

  5. python系列——文件操作的代码

    import numpy as np import os,sys #获取当前文件夹,并根据文件名 def path(fileName): p=sys.path[0]+'\\'+fileName ret ...

  6. 【记录】elasticsearch 注解

    先记录地址,之后再整理 参考地址:https://blog.csdn.net/qq_28364999/article/details/81109666 https://blog.csdn.net/dy ...

  7. StarUML 破解方法2.X(转)

    下载地址:https://www.jb51.net/softs/558248.html#download 在安装目录的:StarUML\www\license\node 找到LicenseManage ...

  8. 一、Redis的安装

    1.下载.解压.编译.安装 # 下载地址 wget http://download.redis.io/redis-stable.tar.gz # 解压 tar xzf redis-stable.tar ...

  9. linux IO模式以及select、poll、epoll详解

  10. iframes

    iframes提供了一个简单的方式把一个网站的内容嵌入到另一个网站中.但我们需要慎重的使用iframe.iframe的创建比其它包括scripts和css的 DOM 元素的创建慢了 1-2 个数量级. ...