c++ primer/第十三章 拷贝控制

1.五种特殊成员函数

  1. 拷贝构造函数
  2. 拷贝赋值函数
  3. 移动构造函数
  4. 移动赋值函数
  5. 析构函数

2.拷贝构造函数

定义:第一个参数是自身类类型的引用,且任何额外参数都有默认值。一般用const,且不用explicit

  • 如果没有拷贝构造函数,系统会送一个。就算定义了其他构造函数(合成构造函数)
  • 将一个对象作为是实參传递给一个非引用类型的形参**(作为参数)**
  • 从一个返回类型为非引用类型的函数返回一个对象**(作为返回值)**
  • 用花括号列表初始化一个数组中的元素或一个聚合类中的成员 string s{}(花括号括起来)
  • 个对象用于给另外一个对象进行初始化(常称为赋值初始化);(赋值)
//直接初始化 - 要求编译器用最普通的函数匹配
string dots(10,'.');
//拷贝初始化 -要求将右侧运算对象拷贝到正在创建的对象中,如果需要的话还要进行类型转换
string s2 = dots;
2.注意:
  1. 拷贝构造函数自己的参数必须是引用类型!!!
    1. 为了调用拷贝构造函数,我们必须拷贝它的实参。:执行拷贝函数时,如果不是引用类型,就需要使用一个实参的拷贝。
    2. 但为了拷贝实参,我们又需要调用拷贝构造函数. :但是为了这个实参的拷贝,我们就有需要调用这个实参的拷贝函数.

3.拷贝赋值运算符

  • 重载 = 号
  • 参数和返回值一般是当前类的引用类型,参数加上const
  • 如果自己不写,系统会默认送一个合成拷贝赋值运算符
    • 把右侧对象(实参)的非static成员赋值到左侧对象上(当前类)
    • 对于数组就是一个个赋值
    • 返回一个指向左侧对象的引用类型
  • 在使用前需要判断是否为自身,是就不做处理,不是需要释放原来的资源

4.析构函数

如果有指针,那么就需要自己定义.如果没有,那么可以用合成析构函数

5.三/五法则

  • 如果自己写了析构函数,那么也需要自己定义拷贝构造函数和重载拷贝赋值运算符
  • 如果写了拷贝构造函数,那么需要重载拷贝赋值运算符

6.=default

  • 作用: 加在类内声明前,显示指定要系统合成默认的(构造)函数,且为内联的
  • 如果不想要指定内联,那么应该在类外定义的时候指定

7.=delete

  • 阻止拷贝,如果加在拷贝函数后面,**那么就不可能再调用到他们.**是在告诉编译器,我们不需要这个函数
  • 析构函数不能有=delete**
  • 合成拷贝成员可能是删除的,如果类内有数据成员不能默认构造,拷贝,复制或者销毁.那么就会把相应的函数置为=delete

8.行为像值的类/行为像指针的类

  • 像值的类: 每个元素都是深拷贝(如string 需要重新new一个)
  • 像指针的类:不能说一个资源释放就释放对应的资源,最好是用智能指针来管控

9.对象移动

  • 在新对象创建拷贝后,需要销毁旧对象时.用移动的方式会更好(移动后原来的就直接无效)
  • 有一些不能被共享的(IO类,unique_ptr类),不能拷贝,但是能移动
  • 移动不应该抛出任何异常,所以一般设置为noexcept
  • 移动源必须是可析构的,进行移动后移动源保存有效,可析构状态

10.右值引用

  • 必须绑定到右值上, 用&&来表示.
  • 只能绑定到一个将要销毁的对象,所以可以自由的将一个右值引用的资源"移动"到另外一个对象上
  • 左值持久,右值短暂
int &&r1 = 42;	//正确
int &&r2 = r1;	//错误,r1是一个左值!
  • 可以对一个左值对象转换为一个对应类型的右值引用(move).但是就必须保证后序只能对他进行赋值和销毁
int &&r3 = std::move(r1);	//可行

11.移动构造函数/ 移动赋值函数

  • 编译器可以合成移动构造函数和移动赋值运算符.

    只有当一个类没有定义任何自己的拷贝控制成员,且类的每个非static成员都可以移动时才会默认合成

  • 但是如果自己定义了拷贝构造,拷贝赋值运算符和析构,那么系统就不会给你生成,移动都会变为拷贝来完成

    如果不满足就会被定义为 =default,这时候调用会报错

xxx::xxx(xxx &&s) noexcept   
{    
}

//移动赋值函数
xxx &xxx::operator=(xxx &&s) noexcept
{
}

12.移动迭代器

  • 移动迭代器的解引用运算符生成的是一个右值引用
  • 可以通过 make_move_iterator 来使得一个普通迭代器转换为一个移动迭代器,原迭代器能干的,移动迭代器也行
  • 特别的: 移动迭代器可以用 uninitialized_copy(未初始化的拷贝)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

公仔面i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值