
1) 【一句话结论】C++智能指针(如std::shared_ptr和std::unique_ptr)通过自动管理对象生命周期(引用计数或独占所有权),避免手动delete导致的内存泄漏,其中shared_ptr适用于资源共享场景,unique_ptr适用于资源独占场景,需注意循环引用、释放时机等关键点。
2) 【原理/概念讲解】智能指针是RAII(资源获取即初始化)的典型应用,用于自动管理动态分配的内存。
3) 【对比与适用场景】
| 类型 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| std::shared_ptr | 多个智能指针共享同一对象,通过引用计数管理 | 引用计数,不能拷贝(拷贝会加引用计数),支持weak_ptr断开循环引用 | 资源需要被多个对象共享(如交易状态、配置对象) | 循环引用导致内存泄漏,需用weak_ptr断开;资源释放时机需匹配业务逻辑 |
| std::unique_ptr | 独占资源所有权,仅一个所有者 | 移动语义(不能拷贝),当所有者离开作用域时自动释放 | 资源独占(如文件句柄、网络连接、数据库连接) | 不能拷贝,需通过std::move转移所有权;资源释放时机需与业务逻辑一致 |
4) 【示例】
示例1(shared_ptr循环引用问题):
class Node {
public:
std::shared_ptr<Node> left;
std::shared_ptr<Node> right;
int data;
Node(int d) : data(d) {}
};
int main() {
auto root = std::make_shared<Node>(1);
auto left = std::make_shared<Node>(2);
auto right = std::make_shared<Node>(3);
root->left = left;
root->right = right;
left->left = std::make_shared<Node>(4);
// 正常场景:引用计数归零,资源释放
// 循环引用场景:root->left = root,导致引用计数始终为2,内存泄漏
}
示例2(unique_ptr独占资源):
class DatabaseConnection {
public:
void connect() { /* 连接数据库 */ }
void query(const std::string& sql) { /* 执行查询 */ }
~DatabaseConnection() { /* 断开连接 */ }
};
int main() {
auto conn = std::make_unique<DatabaseConnection>(); // 独占数据库连接
conn->connect();
// 业务逻辑中,conn离开作用域时自动断开连接
}
5) 【面试口播版答案】
面试官您好,智能指针通过自动管理对象生命周期来避免内存泄漏。具体来说,std::shared_ptr通过引用计数机制,当所有共享指针销毁后,引用计数为0时自动释放资源;std::unique_ptr则通过独占所有权和移动语义,确保资源在所有者离开作用域时被释放。在金融系统中,比如处理交易数据时,shared_ptr可以用于共享交易状态对象,避免手动管理多个指针的引用计数;而unique_ptr用于独占数据库连接,防止资源被重复使用。需要注意的是,shared_ptr的循环引用会导致内存泄漏,金融系统中需避免这种情况,比如使用weak_ptr断开循环引用。另外,资源释放的时机要匹配业务逻辑,比如交易完成时才释放资源,避免提前释放导致数据不一致。
6) 【追问清单】
7) 【常见坑/雷区】