C++ 五法则

2024年8月29日 | 阅读 7 分钟

在本文中,您将学习 C++ 中的五法则及其语法和示例。

五法则指出,如果您的类需要以下任何一项,它可能需要所有这些:

  • 析构函数:当对象超出作用域时,它用于避免资源泄漏。
  • 拷贝构造函数:当对象被拷贝时,它用于正确拷贝类资源。
  • 拷贝赋值运算符:当一个对象被赋值给另一个对象时,它用于拷贝资源。
  • 移动构造函数:当一个对象被移动时,它用于高效地移动资源,而不是拷贝。
  • 移动赋值运算符:当一个对象被移动到另一个对象时,它用于移动资源。

本质上,该规则表示,如果您的类管理指针或文件句柄等资源,您需要正确实现构造函数、析构函数和赋值运算符,以避免清理这些资源时出现问题。遵循该规则可以防止资源泄漏、无效对象状态和不必要的拷贝。

C++ 五法则的重要性

C++ 中存在五法则,因为需要正确管理指针、文件句柄和动态内存分配等资源。以下是遵循五法则的一些关键原因:

  1. 防止资源泄漏:析构函数允许对象在超出作用域时释放/关闭资源。如果没有析构函数,资源可能会泄漏。
  2. 避免拷贝后出现无效状态:拷贝构造函数和赋值运算符正确地将资源所有权从一个对象拷贝到另一个对象。如果没有它们,对象的拷贝最终可能会导致损坏/无效的指针。
  3. 通过移动语义提高效率:移动构造函数和移动赋值运算符转移资源而不是拷贝它们,这速度更快。
  4. 一致性:如果一个类需要一个特殊方法,如析构函数或拷贝构造函数,它可能需要其余方法才能正常工作。该规则设置了一致的预期。
  5. 封装:该规则将资源处理整齐地封装在类中,防止因错误使用/拷贝对象而导致问题。

它为管理资源的类建立了清晰的最佳实践,从而实现正确的程序行为,并避免难以调试的错误。遵循这五个标准方法可确保在初始化、销毁、拷贝或移动对象时正确处理资源。

1. 析构函数

析构函数是一个在对象销毁或超出作用域时自动调用的独特函数。它的主要目的是释放对象在其生命周期中可能获取的资源。

语法

它具有以下语法:

此处,

  • 析构函数的名称与类名相同,前面带有波浪号 (~)
  • 析构函数不带任何参数,也没有返回类型。

示例

让我们举一个例子来说明 C++ 中的析构函数。

在此示例中,析构函数关闭由类打开的文件句柄,以防止对象销毁时发生资源泄漏。资源处理通过析构函数整齐地封装在类中。

2. 拷贝构造函数

拷贝构造函数是一种特殊类型的构造函数,它使用同一类别的现有对象来初始化一个对象。它用于从现有对象初始化新对象。

语法

它具有以下语法:

  • 它是一个构造函数,它接受一个对同一类别对象的引用作为参数。
  • 它有一个引用同一类别类型的单一参数。
  • 参数必须按引用传递,而不是按值传递。
  • 它通常用于在初始化期间深度拷贝对象。

示例

让我们举一个例子来说明 C++ 中的拷贝构造函数

在此示例中,拷贝构造函数通过拷贝其名称和年龄数据成员,将 p2 初始化为 p1 的拷贝。它防止了对象的浅拷贝。

3. 拷贝赋值运算符

拷贝赋值运算符将一个对象的值赋给同一类别的另一个现有对象。它将一个对象赋给同一类别的另一个对象。

语法

它具有以下语法:

  • 它重载了 = 运算符。
  • 它有一个引用同一类别对象的参数。
  • 参数必须按引用传递。
  • 它将传递对象的数据成员赋给当前对象。
  • 它返回对当前对象 (*this) 的引用。

示例

让我们举一个例子来说明 C++ 中的拷贝赋值运算符。

在此示例中,拷贝赋值运算符被重载以将 c1 的值赋给现有 c2 对象。它拷贝成员数据并返回当前更新的对象。

4. 移动构造函数

移动构造函数将资源所有权从一个对象转移到另一个对象,而不是进行拷贝。它用于实现移动语义,它比拷贝更快地转移资源。

语法

它具有以下语法:

示例

让我们举一个例子来说明 C++ 中的移动构造函数

在此处,移动构造函数高效地将数据指针从 v1 转移到 v2。v1 在移动后处于有效的空状态。因此,它转移资源而不是拷贝它们。它实现了高效的移动语义。

5. 移动赋值运算符

移动赋值运算符将资源从一个对象转移到另一个对象,而不是进行拷贝。它用于实现移动语义,它比拷贝更快地转移资源。

语法

它具有以下语法:

  • 它重载了 = 运算符,类似于拷贝赋值。
  • 它接受一个指向同一类别类型的右值引用 (&&)
  • 资源和数据成员从 old_obj 对象转移到当前对象。
  • old_obj 在移动后处于有效但未指定的状态。
  • 它返回对当前对象 (*this) 的引用。

示例

让我们举一个例子来说明 C++ 中的移动赋值运算符

在此处,移动赋值运算符高效地将数据指针从 s1 转移到 s2,而不是创建新拷贝。s1 在移动后处于有效的空状态。因此,它转移资源而不是拷贝它们,实现了移动语义。

示例

让我们看一个 C++ 程序,它演示了所有五个特殊成员函数的使用:析构函数、拷贝构造函数、拷贝赋值运算符、移动构造函数和移动赋值运算符。

输出

Constructor - Allocated memory for 5 integers.
Copy Constructor - Copied 5 integers.
Constructor - Allocated memory for 3 integers.
Copy Constructor - Copied 3 integers.
Move Constructor - Moved resources.
Constructor - Allocated memory for 2 integers.
Move Assignment Operator - Moved resources.
Destructor - Deallocated memory.
Destructor - Deallocated memory.
Destructor - Deallocated memory.
Destructor - Deallocated memory.
Destructor - Deallocated memory.