C++ Primer : 第十三章 : 拷贝控制之对象移动
右值引用
int i = 42;
int &r = i; // 正确,r引用i
int&& rr = i; // 错误,不能将右值引用绑定到左值
int &r2 = i * 42; // 错误,i*42是一个右值
const int& r3 = i * 42;
int&& rr2 = i * 42;
int&& rr1 = 42;
int&& rr2 = rr1; // 错误,表达式rr1是左值
int&& rr3 = std::move(rr1);
move旨在告诉编译器,我们希望把一个左值像右值一样使用它。使用move函数就意味着:除了对rr1赋值或销毁之外,我们不能再使用它。使用move之后,我们就不能对源对象的值做任何假设。
移动构造函数和移动赋值运算符
StrVec::StrVec(StrVec&& s) noexcepd : first(s.first), last_end(s.last_end), cap(s.cap){
s.first = s.last_end = s.cap = nullptr; // 将资源的源对象进入安全状态,对其运行析构函数是安全的。
}
移动构造函数类似拷贝构造函数,第一个形参必须是该类类型的一个引用,而其他额外的参数必须有默认实参。
class StrVec {
public:
StrVec(StrVec&&) noexcept;
/*
*/
};
StrVec::StrVec(StrVec&& s) noexcepd : first(s.first), last_end(s.last_end), cap(s.cap){
s.first = s.last_end = s.cap = nullptr; // 将资源的源对象进入安全状态,对其运行析构函数是安全的。
}
StrVec& StrVec::operator = (StrVec&& rhs) noexcept {
if (this != &rhs) {
free();
first = rhs.first;
last_end = rhs.last_end ;
cap = rhs.cap;
rhs.first = rhs.last_end = rhs.cap = nullptr;
}
return *this;
}
- 与拷贝构造函数不同,移动构造函数被定义为删除的函数的条件是:有类成员定义了自己的拷贝构造函数且未定义移动构造函数,或者是有类成员未定义自己的拷贝构造函数但是编译器不能为其合成移动构造函数。移动赋值运算符的情况类似。
- 如果有类成员的移动构造函数或移动赋值运算符被定义为删除的或不可访问的(例如private),则类的移动构造函数或移动赋值运算符被定义为删除的。
- 类似拷贝构造函数,如果类的析构函数被定义为删除的或不可访问的, 则类的移动构造函数被定义为删除的。
- 类似拷贝赋值运算符,如果有类成员是const或是引用,则类的移动赋值运算符被定义为删除的。
右值引用和成员函数
void push_back(const X&);
void push_back(X&&);
我们就可以为动态内存管理类定义另一个版本的push_back:
class StrVec {
public:
void push_back(const std::string&); // 拷贝元素
void push_back(std::string&&); // 移动元素
// 其他定义
};
void StrVec::push_back(const std::string& s) {
chk_n_alloc();
alloc.construct(last_end++, s);
}
void StrVec::push_back(std::string&& s) {
chk_n_alloc();
alloc.construct(last_end++, std::move(s));
}
右值和左值引用函数:
string s1 = "a value", s2 = "another";
auto n = (s1 + s2).find('a');
在此例中,我们在string的右值上调用成员函数,而还有更令我们惊奇的操作:
s1 + s2 = "wow";
我们对一个右值进行了赋值。
class Foo {
public:
Foo& operator = (const Foo&) &; // 只能向可修改的左值赋值
};
Foo& Foo::operator = (const Foo& rhs)& {
// 赋值操作
return *this;
}
引用限定符可以&或&&, 分别指出this可以指向一个左值或右值,类似const限定符,引用限定符只能用于非static函数,而且必须同时出现在声明和定义中。
对于限定 &的函数,我们只能将它用于左值,限定&&的函数,只能用于右值。
class Foo {
public:
Foo someMem() & const;// 错误,const必须在引用限定符之前
Foo anotherMem() const &; // 正确
};
class Foo {
public:
Foo someMem() &;
Foo anotherMem() const; // 错误,必须加上引用限定符
};
C++ Primer : 第十三章 : 拷贝控制之对象移动的更多相关文章
- C++ Primer : 第十三章 : 拷贝控制之拷贝控制和资源管理
定义行为像值的类 行为像值的类,例如标准库容器和std::string这样的类一样,类似这样的类我们可以简单的实现一个这样的类HasPtr. 在实现之前,我们需要: 定义一个拷贝构造函数,完成stri ...
- C++ Primer : 第十三章 : 拷贝控制之拷贝、赋值与销毁
拷贝构造函数 一个构造函数的第一个参数是自身类类型的引用,额外的参数(如果有)都有默认值,那么这个构造函数是拷贝构造函数.拷贝构造函数的第一个参数必须是一个引用类型. 合成的拷贝构造函数 在我们没 ...
- C++ Primer : 第十三章 : 拷贝控制示例
/* Message.h */ #ifndef _MESSAGE_H_ #define _MESSAGE_H_ #include <iostream> #include <strin ...
- [C++ Primer] : 第13章: 拷贝控制
拷贝, 赋值与销毁 当定义一个类时, 我们显示地或隐式地指定在此类型的对象拷贝, 移动, 赋值和销毁时做什么. 一个类通过定义5种特殊的成员函数来控制这些操作, 包括: 拷贝构造函数, 拷贝赋值运算符 ...
- 【C++ Primer 第十三章】4. 拷贝控制示例
拷贝控制示例 #include<iostream> #include<string> #include<set> #include<vector> us ...
- 《C++ Primer》笔记 第13章 拷贝控制
拷贝和移动构造函数定义了当用同类型的另一个对象初始化本对象时做什么.拷贝和移动赋值运算符定义了将一个对象赋予同类型的另一个对象时做什么.析构函数定义了当此类型对象销毁时做什么.我们称这些操作为拷贝控制 ...
- C++Primer 第十三章
//1.当定义一个类时,我们显示地或隐式地指出在此类型的对象(注意这里是此类型的对象,而不包括此类型的指针)拷贝,移动,赋值,销毁时做什么.一个类通过定义五种特殊的成员函数来控制这些操作:拷贝构造函数 ...
- 【c++ Prime 学习笔记】第13章 拷贝控制
定义一个类时,可显式或隐式的指定在此类型对象上拷贝.移动.赋值.销毁时做什么.通过5种成员函数实现拷贝控制操作: 拷贝构造函数:用同类型的另一个对象初始化本对象时做什么(拷贝初始化) 拷贝赋值算符:将 ...
- C++ Primer 5th 第13章 拷贝控制
当一个对象的引用或者指针离开作用域时,析构函数不会执行. 构造函数有初始化部分(初始化列表)和函数体. 析构函数有析构部分和函数,但析构函数的析构部分是隐式的.
随机推荐
- 如何很好的使用Linq的Distinct方法
Person1: Id=1, Name="Test1" Person2: Id=1, Name="Test1" Person3: Id=2, Name=&quo ...
- 如何让一个DIV浮动在另一个DIV上面
直接上DEMO了 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3 ...
- 浅谈JavaScript中的闭包
浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...
- linux 下安装安装rz/sz命令
一.软件安装 root 账号登陆后,依次执行以下命令: cd /tmp wget http://www.ohse.de/uwe/releases/lrzsz-0.12.20.tar.gz http:/ ...
- (五)socket实践编程
1.服务器端程序编写 (1)socket(2)bind(3)listen(4)accept,返回值是一个fd,accept正确返回就表示我们已经和前来连接我的客户端之间建立了一个TCP连接了,以后我们 ...
- 机器学习职位 & 面经
http://www.cnblogs.com/peileyuan/p/4775453.html <浅谈机器学习的职业发展方向> http://blog.sina.com.cn/s/blog ...
- Head First 设计模式 --5 单例模式
单例模式:确保一个类只有一个实例,并提供一个全局访问点.用到的设计原则:1.封装变化2.组合优于集成3.针对接口变成而不是针对实现4.为交互对象之间的松耦合设计而努力5.类应该对扩展开放,对修改关闭6 ...
- ANSI C与GNU C
GNU计划,又称革奴计划,是由Richard Stallman在1983年9月27日公开发起的.它的目标是创建一套完全自由的操作系统.它在编写linux的时候自己制作了一个标准成为 GNU C标准.A ...
- gameui-for-phaser-js更新到最新版本
Hola Cantk是一个功能强大的游戏引擎,它拥有丰富的GUI控件,配合Hola Studio可以快速开发出游戏的UI界面.Phaser是一个流行而且强大的游戏引擎,但是它的GUI控件很少,而且缺乏 ...
- MySQL 死锁问题分析
转载: MySQL 死锁问题分析 线上某服务时不时报出如下异常(大约一天二十多次):"Deadlock found when trying to get lock;". Oh, M ...