在C++中,构造函数(Constructor)和析构函数(Destructor)是类的特殊成员函数,它们在对象的生命周期中扮演着重要的角色。
构造函数
构造函数是一种特殊的成员函数,它的主要目的是在创建对象时初始化对象。当使用new操作符创建对象、使用类类型进行值初始化、或者直接声明类的对象时,构造函数会被自动调用。
特点:
- 构造函数的名字必须与类名完全相同(包括大小写)。
- 构造函数没有返回类型,甚至连void也没有。
- 构造函数可以有参数,也可以有重载的构造函数。
- 构造函数可以是public、protected或private的,但通常它们是public的,以便在类的外部创建对象。
- 如果类中没有定义构造函数,编译器会提供一个默认的构造函数,该构造函数不接受任何参数,并且不对任何成员进行初始化(对于内置类型成员,其初始值是未定义的)。
示例:
class MyClass {
public:
MyClass() { // 默认构造函数
// 初始化代码
}
MyClass(int x) : value(x) { // 带参数的构造函数
// 初始化代码
}
private:
int value;
};
MyClass obj1; // 调用默认构造函数
MyClass obj2(10); // 调用带参数的构造函数
析构函数
析构函数是另一种特殊的成员函数,它在对象生命周期结束时被自动调用,用于执行清理工作,如释放对象占用的资源。
特点:
析构函数的名字是在类名前加上波浪号(~)。
析构函数不接受任何参数,也没有返回类型(连void也没有)。
每个类只能有一个析构函数。
析构函数可以是virtual的,这在处理基类指针指向派生类对象时特别有用,可以实现多态删除。
如果类中没有定义析构函数,编译器会提供一个默认的析构函数,该析构函数什么也不做。
示例:
#include <iostream>
class MyClass {
private:
int* ptr; // 指向动态分配的整数的指针
public:
// 构造函数
MyClass(int value) {
// 动态分配内存
ptr = new int(value);
std::cout << "Constructor called, allocated memory for " << *ptr << std::endl;
}
// 析构函数
~MyClass() {
// 释放内存
if (ptr != nullptr) {
delete ptr;
ptr = nullptr; // 避免野指针
std::cout << "Destructor called, memory freed" << std::endl;
}
}
// 一个成员函数,用于演示访问动态分配的内存
void showValue() {
std::cout << "Value: " << *ptr << std::endl;
}
};
int main() {
// 创建MyClass的对象
MyClass obj(10);
obj.showValue(); // 显示值
// 当obj离开作用域时,其析构函数将被自动调用
// 释放ptr指向的内存
return 0;
}
注意事项:
- 构造函数和析构函数是自动调用的,不需要(也不能)手动调用它们。
- 如果在构造函数中抛出异常,并且对象已经部分构造(即已经调用了某些成员的构造函数),则这些成员的析构函数会被自动调用,以进行清理。然后,整个对象的构造过程失败,不会调用类的析构函数。
- 析构函数通常用于释放对象占用的资源,如动态分配的内存、文件句柄、网络连接等。如果类管理了这些资源,则必须在析构函数中释放它们,以避免内存泄漏或其他资源泄露问题。