C++类的默认成员函数有哪些

发布时间:2022-02-18 09:12:35 作者:iii
来源:亿速云 阅读:213
# C++类的默认成员函数有哪些

## 引言

在C++面向对象编程中,类(class)是构建程序的基础模块。当我们定义一个类时,即使不显式声明某些成员函数,编译器也会自动为我们生成一些默认的成员函数。这些默认成员函数在对象的生命周期中扮演着重要角色,理解它们的存在和行为对于编写正确、高效的C++代码至关重要。

本文将详细探讨C++类中的6个默认成员函数,包括它们的特性、使用场景以及注意事项,帮助开发者更好地掌握C++对象模型的核心机制。

---

## 一、默认成员函数概述

### 1.1 什么是默认成员函数
默认成员函数是指当类定义中未显式声明时,由编译器自动生成的成员函数。这些函数包括:

1. 默认构造函数
2. 默认析构函数
3. 默认拷贝构造函数
4. 默认拷贝赋值运算符
5. 默认移动构造函数(C++11引入)
6. 默认移动赋值运算符(C++11引入)

### 1.2 生成条件
这些函数仅在**需要时**才会被生成,且满足以下条件:
- 类中没有用户自定义的对应函数
- 没有被`= delete`显式删除
- 类的所有成员和基类支持相应操作

```cpp
class Example {
    // 编译器将根据需要生成所有默认成员函数
};

二、六大默认成员函数详解

2.1 默认构造函数

基本特性

行为特点

class Widget {
public:
    int x;  // 未初始化
    std::string s;  // 调用默认构造函数
};

Widget w;  // 使用默认构造函数

注意事项


2.2 默认析构函数

基本特性

行为特点

class ResourceHolder {
    FILE* file;
public:
    ~ResourceHolder() { 
        if(file) fclose(file);  // 需要自定义资源管理
    }
};

重要规则


2.3 默认拷贝构造函数

基本特性

默认行为

class String {
    char* data;
public:
    // 默认拷贝构造函数会导致多个对象共享同一内存
    // 通常需要自定义深拷贝
    String(const String& other) : 
        data(new char[strlen(other.data)+1]) {
        strcpy(data, other.data);
    }
};

三法则

如果类需要自定义以下任一函数,通常需要全部三个: 1. 析构函数 2. 拷贝构造函数 3. 拷贝赋值运算符


2.4 默认拷贝赋值运算符

基本特性

默认实现

class Array {
    int* ptr;
    size_t size;
public:
    // 不安全的自赋值处理
    Array& operator=(const Array& other) {
        delete[] ptr;
        ptr = new int[other.size];
        size = other.size;
        std::copy(other.ptr, other.ptr+size, ptr);
        return *this;
    }
};

注意事项


2.5 默认移动构造函数(C++11)

基本特性

默认行为

class Buffer {
    char* data;
    size_t length;
public:
    Buffer(Buffer&& other) noexcept :
        data(other.data), length(other.length) {
        other.data = nullptr;  // 置空源对象
        other.length = 0;
    }
};

五法则

对于资源管理类,建议同时提供: 1. 析构函数 2. 拷贝构造函数 3. 拷贝赋值运算符 4. 移动构造函数 5. 移动赋值运算符


2.6 默认移动赋值运算符(C++11)

基本特性

实现要点

Buffer& operator=(Buffer&& other) noexcept {
    if(this != &other) {
        delete[] data;  // 释放现有资源
        data = other.data;
        length = other.length;
        other.data = nullptr;
        other.length = 0;
    }
    return *this;
}

异常安全


三、特殊成员函数的控制

3.1 显式默认化

使用= default显式请求编译器生成默认实现:

class Defaulted {
public:
    Defaulted() = default;
    Defaulted(const Defaulted&) = default;
    ~Defaulted() = default;
};

3.2 显式删除

使用= delete禁止特定操作:

class NonCopyable {
public:
    NonCopyable(const NonCopyable&) = delete;
    NonCopyable& operator=(const NonCopyable&) = delete;
};

3.3 生成规则总结

函数 生成条件
默认构造函数 无任何构造函数
析构函数 总是生成
拷贝构造函数 无用户定义拷贝操作
拷贝赋值运算符 无用户定义拷贝赋值
移动操作 无用户定义拷贝/移动/析构函数

四、实践建议

  1. 遵循0/3/5法则:根据需求实现完整的特殊函数集
  2. 优先使用移动语义:对于资源管理类实现移动操作
  3. 多态基类使用虚析构函数:防止派生类内存泄漏
  4. 谨慎使用默认拷贝:资源管理类应禁用或自定义
  5. 标记noexcept:移动操作应保证不抛出异常
class BestPractice {
public:
    // 显式声明所有特殊成员函数
    BestPractice() = default;
    ~BestPractice() = default;
    BestPractice(const BestPractice&) = default;
    BestPractice& operator=(const BestPractice&) = default;
    BestPractice(BestPractice&&) noexcept = default;
    BestPractice& operator=(BestPractice&&) noexcept = default;
};

结语

理解C++默认成员函数是掌握对象生命周期管理的关键。从C++98的三法则到C++11的五法则,语言演进不断改进对象操作的效率和安全性。合理利用这些默认函数可以减少代码冗余,同时通过自定义实现可以精确控制对象行为。开发者应当根据类的具体需求,选择适当的策略来处理这些特殊成员函数。

“Effective C++的核心在于理解C++默默编写并调用了哪些函数。” —— Scott Meyers “`

推荐阅读:
  1. 类的默认成员函数
  2. C++6个默认成员函数

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

c++

上一篇:SpringBoot怎么配置文件给实体注入值

下一篇:Java单线程会导致死锁吗

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》