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/

目录
相关文章
|
编译器 C++
《Effective C++ 改善程序与设计的55个具体做法》 第一章 笔记
《Effective C++ 改善程序与设计的55个具体做法》 第一章 笔记
180 0
|
编译器 数据安全/隐私保护 C++
c++primer plus 6 读书笔记 第十三章 类继承
c++primer plus 6 读书笔记 第十三章 类继承
178 0
|
C++ 容器
【C/C++笔记】迭代器
【C/C++笔记】迭代器
216 1
|
C++ Windows
FFmpeg开发笔记(三十九)给Visual Studio的C++工程集成FFmpeg
在Windows上使用Visual Studio 2022进行FFmpeg和SDL2集成开发,首先安装FFmpeg至E:\msys64\usr\local\ffmpeg,然后新建C++控制台项目。在项目属性中,添加FFmpeg和SDL2的头文件及库文件目录。接着配置链接器的附加依赖项,包括多个FFmpeg及SDL2的lib文件。在代码中引入FFmpeg的`av_log`函数输出"Hello World",编译并运行,若看到"Hello World",即表示集成成功。详细步骤可参考《FFmpeg开发实战:从零基础到短视频上线》。
889 0
FFmpeg开发笔记(三十九)给Visual Studio的C++工程集成FFmpeg
|
存储 安全 程序员
【C/C++笔记】迭代器范围
【C/C++笔记】迭代器范围
223 0
c++primer plus 6 读书笔记 第十四章 C++中的代码重用
c++primer plus 6 读书笔记 第十四章 C++中的代码重用
172 1
|
SQL 人工智能 算法
技术心得记录:模板函数函数模板FunctionTemplate(C++Primer
技术心得记录:模板函数函数模板FunctionTemplate(C++Primer
|
编译器 C++
《Effective C++ 改善程序与设计的55个具体做法》 第二章 构造/析构/赋值运算 笔记
《Effective C++ 改善程序与设计的55个具体做法》 第二章 构造/析构/赋值运算 笔记
156 0
|
存储 小程序 程序员
Essential C++ 第1章 C++编程基础 (笔记)
Essential C++ 第1章 C++编程基础 (笔记)
193 0
|
算法 C语言 C++
面向考试编程C++笔记
面向考试编程C++笔记