C++——右值引用
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++——右值引用的更多相关文章
- C++右值引用浅析
一直想试着把自己理解和学习到的右值引用相关的技术细节整理并分享出来,希望能够对感兴趣的朋友提供帮助. 右值引用是C++11标准中新增的一个特性.右值引用允许程序员可以忽略逻辑上不需要的拷贝:而且还可以 ...
- C++ 11 中的右值引用
C++ 11 中的右值引用 右值引用的功能 首先,我并不介绍什么是右值引用,而是以一个例子里来介绍一下右值引用的功能: #include <iostream> #include &l ...
- 图说函数模板右值引用参数(T&&)类型推导规则(C++11)
见下图: 规律总结: 只要我们传递一个基本类型是A④的左值,那么,传递后,T的类型就是A&,形参在函数体中的类型就是A&. 只要我们传递一个基本类型是A的右值,那么,传递后,T的类型就 ...
- c++11的右值引用、移动语义
对于c++11来说移动语义是一个重要的概念,一直以来我对这个概念都似懂非懂.最近翻翻资料感觉突然开窍,因此记下.其实搞懂之后就会发现这个概念很简单,并无什么高深的地方. 先说说右值引用.右值一般指的是 ...
- VS2012 error C2664: “std::make_pair”:无法将左值绑定到右值引用
在vs2012(c++)make_pair()改动: C++: template <class T1, class T2> pair<V1, V2> make_pair(T1& ...
- 右值引用、move与move constructor
http://blog.chinaunix.net/uid-20726254-id-3486721.htm 这个绝对是新增的top特性,篇幅非常多.看着就有点费劲,总结更费劲. 原来的标准当中,参数与 ...
- 【转】C++11 标准新特性: 右值引用与转移语义
VS2013出来了,对于C++来说,最大的改变莫过于对于C++11新特性的支持,在网上搜了一下C++11的介绍,发现这篇文章非常不错,分享给大家同时自己作为存档. 原文地址:http://www.ib ...
- move语义和右值引用
C++11支持move语义,用以避免非必要拷贝和临时对象. 具体内容见收藏中的“C++右值引用” .
- [转载] C++11中的右值引用
C++11中的右值引用 May 18, 2015 移动构造函数 C++98中的左值和右值 C++11右值引用和移动语义 强制移动语义std::move() 右值引用和右值的关系 完美转发 引用折叠推导 ...
- C++ 11 右值引用
C++11中引入的一个非常重要的概念就是右值引用.理解右值引用是学习“移动语义”(move semantics)的基础.而要理解右值引用,就必须先区分左值与右值. 注意:左值右值翻译可能有些问题 *L ...
随机推荐
- vue filters 金额转中文大写
capitalAmount(amount: any) { // 汉字的数字 const cnNums = ["零", "壹 ...
- 搜索的应用--计算最优解:Aizu - ALDS1_4_D Allocation
搜索的应用-计算最优解 题目: You are given nn packages of wiwi kg from a belt conveyor in order (i=0,1,...n−1i=0, ...
- python 装饰器 第九步:使用类来作为装饰器
#第九步:使用类来作为装饰器 class kuozhan: #接收装饰器的参数(函数outer) def __init__(self,arg): print(self,arg)#arg就是la sel ...
- Codeforces 1140C(贪心+堆)
题面 传送门 题意: 给出长度为n的序列b,t,定义一个子序列的值为\(\min\{ b_i\} \times \sum t_i\),求所有子序列中值最大的一个,输出最大值 分析 假如固定某个b[i] ...
- Pycharm 激活码2017最新
BIG3CLIK6F-eyJsaWNlbnNlSWQiOiJCSUczQ0xJSzZGIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYXNzaWduZWVOYW1lIjoiI ...
- WPF的Effect效果
一.阴影效果(DropShadowEffect) <TextBlock Text="> <TextBlock.Effect> <DropShadowEffect ...
- 灵活轻便的Table控件,适合复杂样式的内容排版
github仓库地址 https://github.com/gaoyangclub/GYTableViewController 前言 TableView是在项目开发的时候经常用到的组件,几乎百分之八十 ...
- PHP 与Python 读取大文件的区别
php读取大文件的方法 <?php function readFile($file) { # 打开文件 $handle = fopen($file, 'rb'); while (feof($ ...
- 转帖 Java生成和操作Excel文件
JAVA EXCEL API:是一开放源码项目,通过它Java开发人员可以读取Excel文件的内容.创建新的Excel文件.更新已经存在的Excel文件.使用该API非Windows操作系统也可以通过 ...
- C++ 使用老牌库xzip & unzip对文件进行压缩解压
原文链接 https://www.codeproject.com/Articles/7530/Zip-Utils-clean-elegant-simple-C-Win https://www.code ...