C++类三大核心函数:构造函数、析构函数与拷贝构造详解

Elena
Elena
发布时间:2026-10-15| 2人浏览过
原创

本文详细介绍C++类中由编译器默认提供的三个核心函数:构造函数、析构函数和拷贝构造函数,涵盖其语法规范、调用时机、调用规则以及深拷贝与浅拷贝的区别,旨在帮助开发者正确管理对象生命周期和资源。

一. 构造函数

第1步:理解构造函数的作用与特性

在创建类对象后,成员属性若未显式赋值,可能包含随机的“垃圾值”。为确保代码简洁与安全,C++提供了构造函数来一次性完成所有成员属性的初始化。

构造函数的基本特性:

  • 命名:函数名必须与类名完全相同。
  • 返回值:没有返回值类型,甚至不能写 void。
  • 自动触发:在创建对象时由系统自动调用,无需手动调用,且仅执行一次。
  • 重载支持:可以接收参数,因此支持函数重载。

第2步:掌握构造函数的分类与调用方式

构造函数按参数可分为有参构造和无参构造(默认构造);按类型可分为普通构造和拷贝构造。常见的实例化方式包括:

  1. 括号法:如 Person p(10);。注意:定义无参对象时不可加括号 Person p();,否则会被编译器视为函数声明。
  2. 显示法:如 Person p = Person(10);。匿名对象在当前行结束后立即析构。
  3. 隐式转换法:如 Person p = 10;,编译器会自动将其转换为对应的构造调用。
// 构造函数演示
class Person {
public:
    // 无参构造函数
    Person() { cout << "无参构造函数" << endl; }
    
    // 有参构造函数
    Person(int a) : age(a) {
        cout << "有参构造函数" << endl;
    }
    
    // 拷贝构造函数
    Person(const Person& p) : age(p.age) {
        cout << "拷贝构造函数" << endl;
    }
    
    ~Person() { cout << "析构函数" << endl; }
    int age;
};

// 调用示例
int main() {
    Person p1;          // 调用无参构造
    Person p2(18);      // 调用有参构造
    Person p3(p2);      // 调用拷贝构造
    return 0;
}

二. 析构函数

第1步:理解析构函数的职责

析构函数用于在对象生命周期结束前执行清理工作(如释放堆区内存)。它不负责删除对象本身,而是为内存回收做准备。

析构函数特性:

  • 命名:以波浪号 ~ 开头,后接类名。
  • 参数限制:不接受任何参数,因此不可重载。
  • 自动触发:对象销毁前自动调用,仅执行一次。

第2步:析构函数与构造函数的配合

通常遵循“先构造后析构”的顺序。当对象超出作用域或被显式删除时,系统会自动匹配并调用析构函数。

// 析构函数基础演示
class Simple {
public:
    Simple() { cout << "Simple constructed" << endl; }
    ~Simple() { cout << "Simple destructed" << endl; }
};

void test() {
    Simple s; // s在此处离开作用域,触发析构
}
// 程序输出将显示构造后立即析构

三. 拷贝构造函数及其调用时机

第1步:识别拷贝构造触发的三种场景

C++编译器默认提供的拷贝构造函数仅进行简单的值拷贝(浅拷贝),在以下情况会被自动调用:

  1. 对象初始化:使用一个已存在的对象初始化一个新对象,如 Person p2(p1);。
  2. 值传递参数:将对象作为非引用参数传递给函数,如 void doWork(Person p) 被调用时。
  3. 值方式返回:函数以值的方式返回局部对象。
// 拷贝构造时机测试
class Person {
public:
    Person() {} 
    Person(const Person& p) { cout << "Copy Construct" << endl; }
    ~Person() {}
};

// 场景1:初始化
void testInit() { Person man(10); Person newman(man); }

// 场景2:值传递
void func(Person p) {} // 传入对象时触发拷贝构造
void testPass() { Person p; func(p); }

四. 构造函数调用规则与深浅拷贝

第1步:理解编译器的默认行为规则

如果用户未自定义任何构造函数,编译器会提供默认的无参构造、析构和拷贝构造。但存在以下互斥规则:

  • 若用户定义了有参构造函数,编译器不再提供默认无参构造,但仍提供拷贝构造。
  • 若用户定义了拷贝构造函数,编译器不再提供其他默认构造函数。

第2步:区分浅拷贝与深拷贝的风险

浅拷贝风险:默认拷贝构造函数仅复制指针地址。若多个对象指向同一块堆内存,析构时会出现多次 delete,导致程序崩溃或内存泄露。

深拷贝解决方案:在拷贝构造函数中重新申请堆内存,并将原对象数据拷贝至新内存,确保每个对象拥有独立的资源。

// 深拷贝实现示例
class DeepCopyExample {
public:
    int* data;
    
    // 构造函数分配内存
    DeepCopyExample(int val) {
        data = new int(val);
        cout << "Allocated memory for " << *data << endl;
    }
    
    // 深拷贝构造函数
    DeepCopyExample(const DeepCopyExample& other) {
        if (other.data) {
            data = new int(*other.data); // 新开辟空间
            cout << "Deep copied: " << *data << endl;
        } else {
            data = nullptr;
        }
    }
    
    // 析构函数释放内存
    ~DeepCopyExample() {
        if (data) {
            delete data;
            cout << "Freed memory" << endl;
        }
    }
};

int main() {
    DeepCopyExample obj1(100);
    DeepCopyExample obj2(obj1); // 安全拷贝,不会引发双重释放
    return 0;
}

总结

C++类的三大核心函数共同维护了对象的生命周期。构造函数保障初始状态的正确性,析构函数负责资源的安全回收,而拷贝构造函数则决定了对象间的独立性。对于涉及动态内存管理的类,务必重写拷贝构造函数以实现深拷贝,避免潜在的内存错误。以上就是C++类中三大核心函数(构造、析构和拷贝)的详细内容,更多关于C++面向对象特性的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。