2月8日学习c++primer记录

warning: 这篇文章距离上次修改已过223天,其中的内容可能已经有所变动。

1.重载赋值运算符

名字由operator关键字后接想要定义的运算符的符号组成,所以赋值运算符就是一个名为:operator=的函数,运算符函数也有一个返回类型和参数列表。

class Foo
{
public:
    Foo& operator=(const Foo&);//赋值运算符
//...
}

2.定义删除的函数

我们可以将拷贝构造函数与拷贝赋值运算符定义为删除的函数来阻止拷贝
Nocopy(Nocopy &) = delete;
Nocopy &operator=(Nocopy &) = delete;


3.类内的static变量必须在类的外部进行初始化


4.引用计数

在类内增加一个计数器,每次有拷贝就加一,析构函数就减1,减到0了就释放内存


5.移动构造函数和move

move标准库函数,定义在头文件<utility>头文件中。
关于move需要了解的两个关键点:

  1. reallocate在新内存中构造string时,必须调用move来表示希望使用string的移动构造函数
  2. 我们通常不为move提供一个using声明,当我们使用move时直接调用std::move而不是move

在某些情况下对象拷贝后就立即被销毁了。在这些情况下移动而非拷贝对象会大幅提升性能。同时IO类或unique_ptr这样的类包含不可以被共享的资源,因此这些对象不能被拷贝但是可以被移动。

为了支持移动操作,引入一种新的引用类型--右值引用。

右值引用

  1. 通过&&来获得右值引用
  2. 性质:只能绑定到一个将要销毁的对象。
  3. 左值引用与右值引用的区别:
    左值引用不能将其绑定到要求转换的表达式、字面常量或是返回值是右值的表达式

右值有着与之完全相反的绑定特性

int i = 42;
int &r = i;//可以,r引用i
int &&rr = i;//不可以,不能将一个右值引用绑定到左值上
int &r2 = 42 * i;//不可以,i*42是一个右值
const int &r3 = i * 42;//可以,将一个const引用绑定到右值上
int &&rr2 = 42 * i;//可以

可以将一个const左值引用绑定到右值上

左值持久,右值短暂

右值只能绑定到临时对象上,我们得知:

  1. 所有引用对象将要被销毁
  2. 该对象没有其他用户

意味着:使用右值引用的代码可以自由地接管所引用的对象的资源

注意:
变量表达式都是左值,我们不能将一个右值引用绑定到一个右值引用类型的变量上

move

我们可以调用一个名为move的新标准库函数来获得绑定到左值上的右值引用。

int &&rr3 = move(rr1);

调用move就意味着除了对rr1赋值或销毁外不能再使用它

注意:
我们可以销毁一个移后源对象,也可以赋予新值,但是不能使用一个移后源对象的值

移动构造函数样例:

StrVec::StrVec(StrVec &&s) noexcept//移动构造函数不应该抛出任何异常
:elements(s.elements),first_free(s.first_free),caps(s.caps)
{
    //令s进入这样的状态--对其运行析构函数是安全的
    s.elements = s.first_free = s.caps =nullptr;
}

6.三/五法则

所有五个拷贝控制成员应该看作一个整体:如果一个类定义了任何一个拷贝操作,它就应该定义所有五个操作。

五个拷贝控制成员:拷贝构造函数,拷贝赋值运算符,移动构造函数,移动赋值运算符,析构函数


7.移动迭代器

uninitialized_copy(first,second,result);
first与second是两个迭代器,范围是[first,second)
result是赋值给的元素的首个位置

auto last = uninitialized_copy(begin(),end(),result);

make_move_iterator()将一个普通的迭代器转换成一个移动迭代器

看到527页

添加新评论