Learning C++ (Day 2)
1. 智能指针 unique_ptr
std::unique_ptr<Shape> p = std::make_unique<Circle>(); 与Shape* p = new Circle(); 在底层调用多态函数时的行为完全一致,但在生命周期管理、异常安全、所有权表达及工程防错上有着本质区别。
std::unique_ptr vs 裸指针(多态场景对比)
| 维度 | Shape* p = new Circle();(裸指针) |
std::unique_ptr<Shape> p = std::make_unique<Circle>();(智能指针) |
|---|---|---|
| 生命周期 | 手动管理:必须显式编写 delete p;,极易遗忘导致泄漏 |
RAII 自动管理:离开所在作用域({})自动释放,零泄漏 |
| 异常安全 | 差:提前 return 或中途抛出异常,delete 被跳过即泄漏 |
强:栈展开(Stack Unwinding)保证必定触发析构与释放 |
| 所有权语义 | 模糊:无法表达是“拥有者(Owner)”还是“借用者(Borrower)” | 清晰独占:明确表达独占该资源,禁止拷贝,仅支持所有权移动(Move-only) |
| 防错能力 | 低:允许随意浅拷贝,极易造成悬垂指针(Dangling Pointer)与重复释放(Double-Free) | 高:编译器直接拦截拷贝构造/赋值,从源头杜绝多次释放 |
| 性能/空间开销 | 64 位平台占 8 字节 | 零开销抽象:同样仅占 8 字节,无引用计数,内联后机器码与原生指针相同 |
| 基类虚析构 | 必须具备:缺失 virtual ~Base() 触发未定义行为(UB) |
必须具备:默认删除器底层仍执行 delete,同样依赖基类虚析构 |
核心工程实践准则
- 拥有即管理:堆对象创建与所有权持有统一使用
std::make_unique<Derived>(),业务代码杜绝裸new/delete。 - 借用不接管:仅需访问对象接口时,函数形参使用
const Base&(推荐)或Base*(允许空值),不传递智能指针所有权。 - 致命共性约束:多态基类析构函数必须显式声明为虚析构(
virtual ~Base() = default;),智能指针无法替你规避非虚析构的 UB。
2. 纯虚函数 && 抽象类
什么是纯虚函数?在声明虚函数时,在函数声明的末尾加上 = 0,它就成了纯虚函数。纯虚函数没有具体的实现代码(或者说不需要在基类中强制实现),它只定义了函数的名称、参数和返回值类型。
在 C++ 标准中,只要一个类拥有(声明或继承且未实现的)至少一个纯虚函数,它就必然是抽象类。
#include <iostream>
// 抽象类:含纯虚函数,不能实例化
class Animal {
public:
virtual void speak() = 0; // 纯虚函数
virtual ~Animal() = default;
};
// 派生类:必须实现 speak
class Dog : public Animal {
public:
void speak() override {
std::cout << "汪汪!\n";
}
};
int main() {
// Animal a; // ❌ 编译报错:抽象类不能直接创建对象
Dog dog;
Animal* p = &dog; // ✅ 允许使用抽象类指针/引用
p->speak(); // 运行时多态:输出 "汪汪!"
}

浙公网安备 33010602011771号