第十三章:拷贝控制

1.拷贝控制操作
  • 拷贝构造函数
  • 移动构造函数     //用同类型的对象初始化本对象
  • 拷贝赋值运算符
  • 移动赋值运算符    //将一个对象赋予同类型的另一个对象
  • 析构函数       //销毁对象
    注意点:
    ①如果一个类没有定义所有这些拷贝控制成员,编译器会自动为它定义缺失的操作。
    ②声明后加=default来显示要求编译器生成合成的版本,只能对具有合成版本的成员函数使用(默认构造函数&拷贝控制成员)。
    ③声明后加**=delete来定义删除的函数,来阻止该函数的调用,可以对任何函数使用,与=default不同。
    ④< utility >头文件中的move函数调用均采用
    std::move**
    ⑤swap(a,b); //若a和b均为内置类型,此时会调用标准库std::swap,否则按照匹配程度最优的调用
class A
{
public:
	A(const A &a){}                   //拷贝构造函数
	A(const A &&a){}                  //移动构造函数
	A& operator=(const A &a){}        //拷贝赋值运算符
	A& operator=(const A &&a){}       //移动赋值运算符
	~A(){}                            //析构函数
};
2.拷贝构造函数

定义:
构造函数的第一个参数为自身类类型的引用,且任何额外参数都有默认值。编译器生成的合成拷贝构造函数为浅拷贝

使用拷贝构造函数的情况:
  ①用=定义变量时               //Ta = b;
  ②非引用参数传递              // fcn(T v); fcn(a); 这也是参数第一个为&的原因,否则出现死循环
  ③非引用函数返回              // fcn(){… return v;}
  ④列表初始化数组元素            // T arr[size] = {…}
  ⑤容器元素用非emplace添加         // insert()|push()
  ⑥直接初始化时编译器根据参数匹配调用    // T a(b);编译器使用普通函数匹配

3.拷贝赋值运算符
A a1,a2;
a1 = a2;          //将一个对象赋予同类型的另一个对象

合成的拷贝赋值运算符类似合成的拷贝构造函数。

4.析构函数

当变量离开作用域、对象销毁时成员销毁、容器销毁时其元素销毁、delete对象指针,析构函数调用,成员按初始化的逆序销毁。
  一个类自定义了析构函数,基本也需要自定义拷贝赋值运算符和拷贝构造函数,反过来却不一定。

5.移动构造函数和移动赋值运算符

从给定对象窃取资源而不是拷贝资源(指针的移交,之前的指针变量需置nullptr),一般均声明为noexcept(不抛异常,置于参数列表与初始化列表开始的:中间)
  如果一个类定义了自己的拷贝构造函数、拷贝赋值运算符或析构函数,编译器就不会为它合成移动构造函数和移动赋值运算符了。
  移动迭代器解引用生成一个右值引用,通过调用标准库的make_move_iterator函数可将一个普通迭代器转换为一个移动迭代器。copy(make_move_iterator(b),make_move_iterator(e),d);

6.简易的SmartPoint
template<typename T>
class SmartPoint
{
public:
	SmartPoint():users(new size_t(1)),p(new T()){}                        //默认构造函数
	explicit SmartPoint(T *q):users(new size_t(1)),p(q){}                 //内置指针构造函数
	SmartPoint(const SmartPoint &sp):users(sp.users),p(sp.p){++*users;}   //拷贝构造函数
	SmartPoint& operator=(const SmartPoint &sp);                          //赋值运算符重载
	~ SmartPoint();                                                       //析构函数
private:
	size_t *users;
	T *p;
};
template<typename T>
SmartPoint<T>& SmartPoint<T>::operator=(const SmartPoint &sp)       
{
	++*sp.users;    //先对右边指针引用计数+1,解决自我复制存在的问题
	if (--*users==0)
	{
		delete users;
		delete p;
	}
	users = sp.users;
	p = sp.p;
	return *this;
}
template<typename T>
SmartPoint<T>::~ SmartPoint()
{
	if (--*users==0)
	{
		delete users;
		delete p;
	}
}
7.引用限定符
  • 引用限定符可以为 &&&(成员函数参数列表后),且必须同时出现在函数的声明和定义中。
  • 可以和const结合使用,const限定符置前,引用置后,二者均可以作为重载区分。
  • &表示仅能通过左值调用该函数,&&表示仅能通过右值调用该函数,const &均可。
  • 如果一个成员函数有引用限定符,则具有相同参数列表的所有版本都必须有引用限定符。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值