c++Primer——第十三章:拷贝控制

本文详细介绍了C++中的拷贝控制,包括拷贝构造函数、拷贝赋值运算符、移动构造函数、移动赋值运算符和析构函数的作用和规则。还探讨了直接初始化与拷贝初始化的区别,以及在哪些情况下会发生拷贝初始化。文章强调了自定义析构函数通常需要伴随自定义拷贝构造和拷贝赋值运算符,并讲解了使用`default`和`delete`关键字的场景。此外,讨论了引用计数的实现、拷贝并交换技术、StrVec类的实现以及右值引用和std::move在移动语义中的应用。最后,指出了移动构造函数和移动赋值运算符的异常安全性和编译器合成的条件。
摘要由CSDN通过智能技术生成

1、拷贝控制操作

  • 拷贝构造函数
  • 拷贝赋值运算符
  • 移动构造函数
  • 移动赋值运算符
  • 析构函数

2、只要我们显示的定义了一个构造函数,编译器就不会替我们再定义任何形式的构造函数

class A
{
public:
	A(int a):x(a){}
	void set(int a) { x = a; }
	int get() const { return x; }
private:
	int x;
};

void test()
{
	A a; //错误  没有默认构造函数
	A a2(3); //正确
}

但是拷贝构造不同,即使我们定义了其他形式的拷贝构造,编译器也会为我们合成一个拷贝构造

2、直接初始化与拷贝初始化

	string dots(10, '.');	//直接初始化
	string s(dots); //直接初始化
	string s2 = dots; //拷贝初始化
	string s3 = "hello"; //拷贝初始化
	string s4 = string(3, 4); //拷贝初始化

当使用直接初始化时,实际上是要求编译器使用普通的函数匹配来选择与我们提供的参数最匹配的构造函数。当我们使用拷贝初始化时,要求编译器将右侧运算对象拷贝到正在创建的对象中,如果需要的话还要进行类型转换。

如果一个类有移动构造的话,拷贝初始化有时会使用移动构造而非拷贝构造。

拷贝初始化不仅在我们用=定义变量时会发生,在下列情况下也会发生

  • 将一个对象作为实参传递给一个非引用类型的实参
  • 从一个返回类型为非引用类型的函数返回一个对象
  • 用花括号列表初始化一个数组中的元素或一个聚合类中的成员

当我们初始化标准库容器或调用其insert或push成员时,容器会对其元素进行拷贝初始化,与之相对,用emplace成员创建的元素都进行直接初始化。

3、析构的顺序

构造函数是先按照成员在类中出现的顺序对他们进行初始化,然后执行函数体。析构正好相反,先执行函数体,再销毁成员。

4、如果一个类需要自定义析构函数,几乎可以肯定它也需要自定义拷贝赋值运算符和拷贝构造函数。我是这么理解的。需要自定义的析构函数,说明你需要手动释放一些东西,而这些东西一般都是动态分配的,默认的拷贝构造和拷贝赋值运算符并不会在发生拷贝的时候进行动态分配。所以第一句话成立。

5、使用=default来显示要求编译器生成合成的版本

class A
{
public:
	A() = default;
	A(const A&) = default;
	A&am
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值