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

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

本文详细介绍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 相关产品和应用

全部下载

专题列表