C++ 中的显式默认和删除的函数

2025年5月24日 | 阅读 7 分钟

随着 C++11 标准的发布,C++ 中引入了C++显式默认和删除函数,以赋予开发人员对特定成员函数的创建和应用更大的控制权。这些特性允许显式指定默认行为或禁止特定操作,从而增强了代码的清晰性、安全性和可维护性。C++ 中有几种显式默认和删除函数。其中一些函数如下:

1. 显式默认函数 (= default)

a) 成员的默认函数是

如果程序员没有显式声明成员函数,C++ 会自动为它们创建默认实现。这包括移动构造函数、移动赋值运算符、复制构造函数、默认构造函数和复制构造函数。

b) ‘= default’ 语法

使用 = default 语法,开发人员可以要求编译器从 C++11 开始提供成员函数的默认实现。

c) 用例

当编译器提供的默认行为合适时。

通过显式声明期望默认行为来提高代码的可读性。

d) 语法

示例

让我们通过一个例子来说明 C++ 中的显式默认函数 (= default)。

输出

Custom function called.   

说明

1. 包含头文件

为了使用 std::cout 将消息打印到控制台,必须在此行包含标准输入/输出流头文件。

2. 类定义

MyClass 包含显式默认的特殊成员函数:析构函数、复制赋值运算符、移动赋值运算符、默认构造函数、复制构造函数和移动构造函数。

调用自定义成员函数 customFunction 时,会打印一条消息。

3. Main() 函数

在 main 方法中创建了三个 MyClass 类型的对象,例如 obj1、obj2 和 obj3。

  • 在 obj1 的构造过程中使用了默认构造函数。
  • obj1 被作为参数传递给复制构造函数,该函数创建了 obj2。
  • 使用移动构造函数来创建 obj3,并将 obj2 作为输入。
  • 随后通过调用复制赋值运算符将 obj3 的值赋给 obj1。
  • 在使用了移动赋值运算符后,将 std::move(obj3) 的值赋给了 obj2。
  • 最后,调用 obj1 的自定义成员函数 customFunction,导致控制台打印出消息。

此代码演示了显式默认的特殊成员函数的用法,以及 MyClass 类型对象的创建、复制和移动。它还展示了类对象如何调用自定义成员函数。

2. 删除的函数

a) 防止函数使用

在某些情况下,限制特定功能的使用,包括对象复制和移动,可能是更可取的。

b) ‘= delete’ 语法

通过引入 C++11 中的 = delete 语法,程序员可以直接删除一个成员函数,使其无法访问。如果尝试使用已删除的函数,则会产生编译错误。

c) 用例

存在某些情况下类不应使用特定函数(例如,使类无法移动或复制)。

它用于防止意外使用并强制执行特定行为。

d) 语法

示例

让我们通过一个例子来说明 C++ 中的删除函数。

输出

Default constructor called.
Custom function called.   

说明

1. 包含头文件

为了使用 std::cout 将消息打印到控制台,必须在此行包含标准输入/输出流头文件。

2. 类定义

复制构造函数和复制赋值运算符是 NoCopyClass 类的两个已删除成员函数,而默认构造函数是 customFunction。

一旦类的实例被构造,默认构造函数就会输出一条消息。

如果使用复制构造函数和复制赋值运算符,将会出现编译错误,因为它们被显式删除了 (= delete)。

3. Main() 函数

此函数创建一个名为 obj1 的 NoCopyClass 类型对象,调用默认构造函数,并输出一条消息。

  • 它被用来表明复制构造函数和复制赋值运算符已被删除,并将导致编译问题,尝试使用这些方法创建另一个对象(obj2)已被故意注释掉。
  • 调用 obj1 的 customFunction,表明未删除的成员函数仍然可用。

总之,此代码定义了一个名为 NoCopyClass 的类,该类的复制构造函数和复制赋值运算符已被删除,以防止对象被复制。它提供了一个示例,说明已删除的函数如何管理类的行为并识别潜在的编译问题。

C++ 中显式默认和删除的函数的优点

C++ 中显式默认和删除的函数具有以下几项优点:

1. 意图和清晰度

默认函数:当使用 = default 显式声明函数的默认值时,代码更易于访问。它传达了该函数有意使用编译器生成的默认行为的意图。

删除的函数:使用 = delete 表明某些操作被有意禁止。它通过明确说明使用某些函数的限制来提高代码的可读性。

2. 防止意外操作

默认函数:当默认操作应被执行时,确保它们被执行。例如,设置为默认的复制构造函数表明该类是可复制的,并且默认实现是合适的。

删除的函数:禁止某些操作,从而防止意外或不安全的行为。例如,通过删除复制构造函数和复制赋值运算符可以避免意外的对象复制。

3. 防止资源泄露

删除的函数:在资源管理至关重要(例如,管理动态生成的内存)时,显式取消复制操作可以避免意外的资源共享和潜在的内存泄露。

4. 编译器生成的代码

默认函数:依赖编译器生成的代码可以实现更优化和高效的实现。当使用默认函数时,编译器保证会为给定类生成合适的代码。

删除的函数:显式禁用特定操作可以防止为这些函数生成默认代码,从而降低了意外行为的可能性。

5. 强制执行设计约束

删除的函数:它通过阻止可能违反类不变量或类的预期用途的特定操作来帮助强制执行设计约束。

6. 维护和可演化性

默认函数:当函数的默认行为足够时,可以简化代码维护。类将来的更改不需要手动更新这些函数。

删除的函数:显式声明对某些操作的限制有助于防止意外使用,从而更容易随着时间的推移维护和演化代码。

7. 文档和代码审查

默认函数:关于某些函数的预期行为的文档,有助于代码审查和开发人员之间的协作。

删除的函数:清晰地记录约束和限制,使开发人员更容易理解类的预期用途和局限性。

8. 更安全的代码

删除的函数:它防止可能导致资源泄露、运行时错误或未定义行为的某些活动。这有助于编写更安全的代码。

9. 所有权和语义

删除的函数:防止资源的意外共享或数据共享,强制执行所有权语义。为了保证独占所有权,一个管理唯一资源但可以删除复制操作的类。

通过指示特定成员函数的预期行为并防止意外操作,C++ 中的显式默认和删除的函数有助于编写更具表现力、更安全、更易于维护的代码。它们还为强制执行设计约束和传达程序中类的预期用途提供了强大的工具集。