此文要谈的两个概念,算是C++中的big three(构造、赋值和析构)中的1.5个。也是在使用过程中,很容易混淆的两个函数。
它们的相似点:
1、当编写一个类的时候,我们没有显式编写它们,编译器都会自动生成一个具有浅拷贝语义(对逐个成员进行位拷贝)的版本。
2、它们被调用的语句,都极少以函数声明的原型形式进行,而是一些用法会触发编译器对他们的调用。也就是说它们的调用是隐晦的,需要记住它们被调用的几种情况。
不同点(区分此二者的根本):
1、复制构造是构造,它的调用意味着一个对象的从无到有。
原型:1、Type(const Type &); 2、Type(Type &); 注:除此二者,参数列表中的其他写法,一律不被视为复制构造。
常见调用时机:1、Type instance = another_instance; 2、非引用形参被赋值时 3、非引用返回值(return语句)
2、赋值函数,是一个重载成员函数,它被调用一定意味着对一个已经存在的对象进行状态的改变。
原型:1、Type |&| operator=(const Type &); 2、Type |&| operator=(Type &); 3、Type |&| operator=(Type ); 注:|&| 表示引用可选,此三者都被编译器视为可被隐晦调用赋值操作符。但是惯用法只有一个,也就是 Type & operator=(const Type &); 这也是编译器自动合成那个版本。返回本类对象引用,是为了实现链式表达式。
说明:1、函数签名中没有考虑像volatile这样的可加可不加的关键字。2、函数签名中没有考虑带默认形参值的形参问题。不考虑这两点,是为了文章主线明了清晰,不会造成问题的复杂性都然而曾。有兴趣的,可以把这两种情况加进去,再自己总结一下。
本质推演,实例: 在写赋值函数的时候,有一步要进行判断自身赋值的情况,而为什么复制构造函数中不需要?因为,复制构造也是构造,此时还没有自身的存在,何来的自身赋值,即复制构造函数中的参数一定不会是自身,而赋值函数却可以。