C++ 学习第22天:智能指针与异常处理
往期回顾:
C++ 入门19:STL 容器之优先队列(priority_queue)-CSDN博客
C++ 入门第 20 天:STL 容器之无序集合与无序多重集合-CSDN博客
C++ 入门第 21 天:STL 容器之无序映射与无序多重映射-CSDN博客
C++ 学习第22天:智能指针与异常处理
前言
今天我们将学习 C++ 的两个重要概念:智能指针 和 异常处理。
- 智能指针:C++11 引入的智能指针可以帮助我们更安全地管理动态分配的内存,避免内存泄漏。
- 异常处理:C++ 提供了异常处理机制,让我们可以捕获并处理程序运行中的错误。
1. 智能指针(Smart Pointers)
1.1 智能指针概述
智能指针是 C++11 引入的一个重要特性,用于自动管理动态分配的内存资源。它们使得开发者不再需要手动 delete
内存,减少了内存泄漏的风险。C++ 标准库提供了三种智能指针:
unique_ptr
:独占式智能指针,每个unique_ptr
独占一个资源,不能复制,但可以转移所有权。shared_ptr
:共享式智能指针,允许多个指针共享同一个资源,通过引用计数管理内存。weak_ptr
:弱引用智能指针,它不会影响引用计数,主要用于解决shared_ptr
的循环引用问题。
1.2 unique_ptr
示例
unique_ptr
是最简单的智能指针,它提供了对资源的独占控制。unique_ptr
不能被复制,只能通过 std::move()
转移所有权。
#include <iostream>
#include <memory>
using namespace std;
int main() {
// 创建一个 unique_ptr,指向动态分配的整数
unique_ptr<int> p1 = make_unique<int>(10);
cout << "Value pointed by p1: " << *p1 << endl;
// 使用 std::move 转移所有权
unique_ptr<int> p2 = move(p1); // p1 现在为空,所有权已转移到 p2
if (!p1) {
cout << "p1 is now empty." << endl;
}
cout << "Value pointed by p2: " << *p2 << endl;
return 0;
}
输出结果:
Value pointed by p1: 10
p1 is now empty.
Value pointed by p2: 10
1.3 shared_ptr
示例
shared_ptr
允许多个智能指针共享同一块资源,并通过引用计数来管理资源的生命周期。当所有 shared_ptr
对象都超出作用域时,资源会被自动释放。
#include <iostream>
#include <memory>
using namespace std;
int main() {
// 创建一个 shared_ptr,指向动态分配的整数
shared_ptr<int> p1 = make_shared<int>(20);
shared_ptr<int> p2 = p1; // p1 和 p2 共享同一个资源
cout << "Value pointed by p1: " << *p1 << endl;
cout << "Value pointed by p2: " << *p2 << endl;
cout << "Use count of shared_ptr: " << p1.use_count() << endl; // 输出引用计数
return 0;
}
输出结果:
Value pointed by p1: 20
Value pointed by p2: 20
Use count of shared_ptr: 2
1.4 weak_ptr
示例
weak_ptr
是一种不增加引用计数的智能指针。它常用来解决 shared_ptr
引起的循环引用问题。
#include <iostream>
#include <memory>
using namespace std;
int main() {
shared_ptr<int> p1 = make_shared<int>(30);
weak_ptr<int> w1 = p1; // 创建一个 weak_ptr,不影响引用计数
if (auto p2 = w1.lock()) { // lock() 获取一个 shared_ptr
cout << "Weak pointer is valid, value: " << *p2 << endl;
} else {
cout << "Weak pointer is expired." << endl;
}
return 0;
}
输出结果:
Weak pointer is valid, value: 30
1.5 智能指针应用场景
- 自动内存管理:使用智能指针可以有效管理内存,避免内存泄漏和悬挂指针。
- 避免循环引用:
weak_ptr
可以有效地打破shared_ptr
之间的循环引用,防止内存无法释放。
2. C++ 异常处理(Exception Handling)
2.1 异常处理概述
C++ 提供了 try
、catch
和 throw
关键字,用于捕获和处理运行时的错误(异常)。通过异常处理,我们能够在程序出错时不中断程序的运行,而是进行适当的处理。
try
:尝试执行可能引发异常的代码。throw
:当发生异常时,抛出异常对象。catch
:捕获并处理抛出的异常。
2.2 异常处理基本结构
#include <iostream>
using namespace std;
int divide(int a, int b) {
if (b == 0) {
throw "Division by zero error"; // 抛出异常
}
return a / b;
}
int main() {
try {
cout << divide(10, 0) << endl; // 会抛出异常
} catch (const char* msg) {
cout << "Caught exception: " << msg << endl; // 捕获并处理异常
}
return 0;
}
输出结果:
Caught exception: Division by zero error
2.3 异常处理中的常见问题
- 异常安全性:为了保证在异常发生时资源能够正确释放,尽量使用 RAII(资源获取即初始化)模式。
- 自定义异常类型:我们可以通过定义自定义的异常类,来实现更加细粒度的异常处理。
2.4 自定义异常类示例
#include <iostream>
#include <stdexcept> // 提供标准异常类
using namespace std;
class DivisionByZeroException : public exception {
public:
const char* what() const noexcept override {
return "Division by zero error"; // 重载 what() 方法,返回自定义异常信息
}
};
int divide(int a, int b) {
if (b == 0) {
throw DivisionByZeroException(); // 抛出自定义异常
}
return a / b;
}
int main() {
try {
cout << divide(10, 0) << endl; // 会抛出异常
} catch (const DivisionByZeroException& ex) {
cout << "Caught exception: " << ex.what() << endl; // 捕获并处理自定义异常
}
return 0;
}
输出结果:
Caught exception: Division by zero error
2.5 异常处理应用场景
- 输入验证:捕获并处理非法输入。
- 文件操作:捕获文件读写过程中可能出现的异常。
- 内存分配:捕获内存分配失败等异常情况。
结语
以上就是 C++ 中两个重要的特性 智能指针 和 异常处理 的基础知识点了。智能指针:unique_ptr
、shared_ptr
和 weak_ptr
能有效管理内存,避免内存泄漏,并解决循环引用问题。异常处理:C++ 提供了 try
、throw
和 catch
来处理程序中的异常,可以保证程序在发生错误时不会崩溃,而是通过捕获和处理异常来继续执行。这两个概念对于编写更健壮、可靠的 C++ 程序非常重要,大家多看看,一定要掌握。
都看到这里了,点个赞再走呗朋友~
加油吧,预祝大家变得更强!