8.2 构造、析构与生命周期
C++ 对象有精确的生命周期。对象创建时构造函数运行,对象销毁时析构函数运行。这是 C++ 和 Java、Python 的重要差异之一:C++ 允许普通对象直接、确定地管理资源。
构造函数与初始化列表
构造函数和类同名,没有返回类型。它应该让对象一创建就处于有效状态。
cpp
class BankAccount {
private:
std::string owner_;
double balance_;
public:
BankAccount(std::string owner, double balance)
: owner_(owner), balance_(balance) {}
};冒号后面的部分叫成员初始化列表。它会在构造函数体执行之前初始化成员。数据成员应优先用初始化列表,尤其是 const 成员、引用成员,以及 std::string 这类类类型成员。
cpp
class Student {
private:
const int id_;
std::string name_;
public:
Student(int id, std::string name)
: id_(id), name_(name) {}
};如果想在构造函数体里给 id_ 赋值,就太晚了,因为 const 成员必须初始化,不能之后再赋值。
正在加载交互实验...
正在加载概念检查...
正在加载本节练习...
重载构造函数与委托构造函数
C++ 类可以提供多个构造函数。当类既有完整形式,也有方便的默认形式时,这很有用。
cpp
class Timer {
private:
int seconds_;
public:
Timer() : Timer(0) {}
Timer(int minutes, int seconds)
: seconds_(minutes * 60 + seconds) {}
explicit Timer(int seconds)
: seconds_(seconds) {}
};Timer() : Timer(0) {} 是委托构造函数:它复用同一个类中的另一个构造函数。explicit 可以避免意外的隐式转换,比如把一个 int 悄悄当成 Timer 传入。
正在加载概念检查...
正在加载本节练习...
析构函数与 RAII
析构函数写作 ~ClassName()。当对象离开作用域,或者堆对象被 delete 销毁时,它会自动运行。
cpp
class Buffer {
private:
int *data_;
int size_;
public:
explicit Buffer(int size)
: data_(new int[size]), size_(size) {}
~Buffer() {
delete[] data_;
}
};这种模式叫 RAII:Resource Acquisition Is Initialization。对象在构造函数中获得资源,在析构函数中释放资源。RAII 是安全 C++ 设计的核心。
初学代码中应优先使用标准库类型,例如 std::string、std::vector 和智能指针。它们已经实现了 RAII。但理解析构函数,才能明白这些类型为什么安全。
正在加载交互实验...
正在加载概念检查...
正在加载本节练习...