18、C++ Primer 4th 笔记,复制控制

简介: 1、显式构造函数 复制构造函数是一种特殊构造函数,具有单个形参,该形参(常用 const 修饰)是对该类类型的引用。当定义一个新对象并用一个同类型的对象对它进行初始化时,将显式使用复制构造函数。当将该类型的对象传递给函数或函数返回该类型的对象时,将隐式使用复制构造函数。

1、显式构造函数

复制构造函数是一种特殊构造函数,具有单个形参,该形参(常用 const 修饰)是对该类类型的引用。当定义一个新对象并用一个同类型的对象对它进行初始化时,将显式使用复制构造函数。当将该类型的对象传递给函数或函数返回该类型的对象时,将隐式使用复制构造函数。

编译器自动执行类中非static数据成员的析构函数。

2赋值操作符可以通过指定不同类型的右操作数而重载

3、有一种特别常见的情况需要自己定义的复制控制成员的:类具有指针成员。

4C++支持两种初始化形式:直接初始化和复制初始化。复制初始化使用=,而直接初始化将初始化放在圆括号中。

当用于类类型对象时,初始化的复制形式和直接形式有所不同:直接初始化直接调用与实参匹配的构造函数,复制初始化总是调用复制构造函数。复制初始化首先使用指定构造函数创建一个临时对象,然后用复制构造函数将那个临时对象复制到正在创建的对象:

示例

string null_book = "00000"; //拷贝构造函数
string dotc(10, '.'); //直接初始化
string empty_copy = string(); //拷贝构造函数
string empty_direct; //直接初始化

5、以非引用类型作为返回值时,将返回return语句中的值的副本。

6、合成的复制构造函数

如果我们没有定义复制构造函数,编译器就会为我们合成一个。合成复制构造函数的行为是,执行逐个成员初始化,将新对象初始化为原对象的副本。

所谓“逐个成员”,指的是编译器将现在对象的每个非 static 成员,依次复制到正创建的对象。只有一个例外,每个成员的类型决定了复制该成员的含义。合成复制构造函数直接复制内置类型成员的值,类类型成员使用该类的复制构造函数进行复制。数组成员的复制是个例外。虽然一般不能复制数组,但如果一个类具有数组成员,则合成复制构造函数将复制数组。复制数组时合成复制构造函数将复制数组的每一个元素。

7、大多数类应定义复制构造函数和默认构造函数。不允许复制的类对象只能作为引用传递给函数或从函数返回,它们也不能用作容器的元素。只有不存在其他构造函数时才合成默认构造函数。

8、内置类型的赋值运算返回对左操作数的引用。

示例

class Sales_item
{
public:
Sales_item& operator=(const Sales_item&rhs)
{
isbn = rhs.isbn;
units_sold = rhs.units_sold;
revenue = rhs.revenue;
return *this; //返回左操作数的引用
}
};

9、合成赋值操作符与合成复制构造函数的操作类似。它会执行逐个成员赋值:右操作数对象的每个成员赋值给左操作数对象的对应成员。除数组之外,每个成员用所属类型的常规方式进行赋值。对于数组,给每个数组元素赋值。

10、析构函数

当对象的引用或指针超出作用域时,不会运行析构函数。只有删除指向动态分配对象的指针或实际对象(不是对象的引用)超出作用域时,才会运行析构函数。

如果类需要析构函数,则它也需要赋值操作和复制构造函数,这是一个有用的经验法则(通常称为三法则)。

11、与复制构造函数或赋值操作符不同,编译器总是会我们合成一个析构函数。合成析构函数按对象创建时的逆序撤销每个非static成员。合成析构函数并不删除指针成员所指向的对象。

12、析构函数没有形参,不能重载。即使我们编写了自己的析构函数,合成析构函数仍然运行。(先运行自定义的,再运行合成的)

13、析构函数对撤销内置类型或指针类型的成员没有影响。赋值操作必须是类的成员并且必须返回对类对象的引用。

    关于复制构造函数中涉及的深拷贝,浅拷贝,及与赋值操作的异同,可以参见下列文章。

参考

[1] http://blog.163.com/zhoumhan_0351/blog/static/3995422720100250413207/

[2] http://blog.163.com/zhoumhan_0351/blog/static/39954227201032845132592/

[3] http://blog.163.com/zhoumhan_0351/blog/static/399542272010318112048522/

[4] http://blog.163.com/zhoumhan_0351/blog/static/39954227201032092854732/

[5] http://blog.163.com/zhoumhan_0351/blog/static/3995422720100284731826/

[6] http://blog.163.com/zhoumhan_0351/blog/static/39954227201012465955824/

目录
相关文章
|
29天前
|
存储 编译器 C语言
C++入门: 类和对象笔记总结(上)
C++入门: 类和对象笔记总结(上)
34 0
|
3月前
|
设计模式 安全 编译器
Effective C++55 笔记
Effective C++55 笔记
21 0
|
2月前
|
机器学习/深度学习 算法 编译器
【C++】自学终极笔记
【C++】自学终极笔记
150 0
|
3月前
|
C++
来自C++ Primer 5的函数指针的定义,调用等
来自C++ Primer 5的函数指针的定义,调用等
15 0
|
3月前
|
存储 算法 C++
《C++ STL开发技术引导》 第五章-C++ STL泛化技术分析笔记
《C++ STL开发技术引导》 第五章-C++ STL泛化技术分析笔记
|
3月前
C++2.0(C++11) 笔记 二
C++2.0(C++11) 笔记 二
20 0
|
3月前
|
编译器 容器
C++11 (C++2.0)笔记 一
C++11 (C++2.0)笔记 一
33 0
|
4月前
|
C语言 C++ iOS开发
嵌入式c++软件开发笔记 第六讲
嵌入式c++软件开发笔记 第六讲
16 0
|
4月前
|
算法 编译器 C++
嵌入式c++软件开发笔记第五讲
嵌入式c++软件开发笔记第五讲
17 0
|
4月前
|
安全 Java 编译器
嵌入式c++软件开发第四讲笔记
嵌入式c++软件开发第四讲笔记
18 0

相关实验场景

更多