C++智能指针使用指南(auto_ptr, unique_ptr, shared_ptr, weak_ptr)
在 C++ 中,智能指针是管理动态分配内存的重要工具,它们可以自动释放内存,避免内存泄漏。以下是四种主要智能指针的详细介绍:
1. auto_ptr (已废弃)
基本特性
C++98 引入,C++17 中已移除
具有所有权转移语义
示例代码
cpp
#include <memory>
#include <iostream>void autoPtrExample() {std::auto_ptr<int> p1(new int(10));std::cout << *p1 << std::endl; // 输出: 10std::auto_ptr<int> p2 = p1; // 所有权转移// std::cout << *p1 << std::endl; // 错误!p1 现在为空std::cout << *p2 << std::endl; // 输出: 10
}问题
所有权转移不明确,容易导致错误
不支持数组
不能在 STL 容器中使用
2. unique_ptr (C++11)
基本特性
独占所有权,不能拷贝,只能移动
轻量级,无额外开销
支持自定义删除器
支持数组
示例代码
cpp
#include <memory>
#include <iostream>void uniquePtrExample() {// 基本用法std::unique_ptr<int> p1(new int(20));std::cout << *p1 << std::endl; // 输出: 20// 移动语义std::unique_ptr<int> p2 = std::move(p1);std::cout << *p2 << std::endl; // 输出: 20// p1 现在为空// 使用 make_unique (C++14)auto p3 = std::make_unique<int>(30);// 数组支持auto p4 = std::make_unique<int[]>(5);p4[0] = 1;p4[1] = 2;// 自定义删除器auto deleter = [](int* p) {std::cout << "Deleting int: " << *p << std::endl;delete p;};std::unique_ptr<int, decltype(deleter)> p5(new int(50), deleter);
}3. shared_ptr (C++11)
基本特性
共享所有权,使用引用计数
支持拷贝和赋值
线程安全(引用计数操作)
支持自定义删除器
示例代码
cpp
#include <memory>
#include <iostream>class MyClass {
public:MyClass(int val) : value(val) {std::cout << "MyClass constructed: " << value << std::endl;}~MyClass() {std::cout << "MyClass destroyed: " << value << std::endl;}void print() {std::cout << "Value: " << value << std::endl;}private:int value;
};void sharedPtrExample() {// 创建 shared_ptrstd::shared_ptr<MyClass> p1 = std::make_shared<MyClass>(100);
rd.xjyl.gov.cn/upload/1982074929729208321.html
rd.xjyl.gov.cn/upload/1982074929775345664.html
rd.xjyl.gov.cn/upload/1982074929792122880.html
rd.xjyl.gov.cn/upload/1982074929871814656.html
rd.xjyl.gov.cn/upload/1982074929980866560.html
rd.xjyl.gov.cn/upload/1982074930068946944.html
rd.xjyl.gov.cn/upload/1982074930337382400.html
rd.xjyl.gov.cn/upload/1982074930408685568.html
rd.xjyl.gov.cn/upload/1982074930429657088.html
rd.xjyl.gov.cn/upload/1982074930551291904.html
rd.xjyl.gov.cn/upload/1982074930614206464.html
rd.xjyl.gov.cn/upload/1982074930635177984.html
rd.xjyl.gov.cn/upload/1982074930706481152.html
rd.xjyl.gov.cn/upload/1982074930719064064.html
rd.xjyl.gov.cn/upload/1982074931075579904.html
rd.xjyl.gov.cn/upload/1982074931146883072.html
rd.xjyl.gov.cn/upload/1982074931247546368.html
rd.xjyl.gov.cn/upload/1982074931247546369.html
rd.xjyl.gov.cn/upload/1982074931373375488.html
rd.xjyl.gov.cn/upload/1982074931369181185.html
rd.xjyl.gov.cn/upload/1982074931369181184.html
rd.xjyl.gov.cn/upload/1982074931570507776.html
rd.xjyl.gov.cn/upload/1982074931604062208.html
rd.xjyl.gov.cn/upload/1982074931725697024.html{std::shared_ptr<MyClass> p2 = p1; // 引用计数 +1p2->print();std::cout << "Use count: " << p1.use_count() << std::endl; // 输出: 2} // p2 析构,引用计数 -1std::cout << "Use count: " << p1.use_count() << std::endl; // 输出: 1p1->print();// 自定义删除器std::shared_ptr<MyClass> p3(new MyClass(200), [](MyClass* p) {std::cout << "Custom deleter called" << std::endl;delete p;});
}4. weak_ptr (C++11)
基本特性
不拥有对象所有权
解决 shared_ptr 循环引用问题
必须从 shared_ptr 创建
循环引用问题示例
cpp
#include <memory>
#include <iostream>class Node {
public:std::shared_ptr<Node> next;std::shared_ptr<Node> prev;~Node() {std::cout << "Node destroyed" << std::endl;}
};void circularReferenceProblem() {auto node1 = std::make_shared<Node>();auto node2 = std::make_shared<Node>();node1->next = node2; // 循环引用node2->prev = node1; // 内存泄漏!// node1 和 node2 的引用计数永远不会为 0
}使用 weak_ptr 解决循环引用
cpp
class NodeSafe {
public:std::shared_ptr<NodeSafe> next;std::weak_ptr<NodeSafe> prev; // 使用 weak_ptr~NodeSafe() {std::cout << "NodeSafe destroyed" << std::endl;
rd.xjyl.gov.cn/upload/1982074931901857792.html
rd.xjyl.gov.cn/upload/1982074931914440704.html
rd.xjyl.gov.cn/upload/1982074932023492608.html
rd.xjyl.gov.cn/upload/1982074932027686912.html
rd.xjyl.gov.cn/upload/1982074932086407168.html
rd.xjyl.gov.cn/upload/1982074932115767296.html
rd.xjyl.gov.cn/upload/1982074932203847680.html
rd.xjyl.gov.cn/upload/1982074932262567936.html
rd.xjyl.gov.cn/upload/1982074932291928064.html
rd.xjyl.gov.cn/upload/1982074932317093888.html
rd.xjyl.gov.cn/upload/1982074932392591360.html
rd.xjyl.gov.cn/upload/1982074932367425536.html
rd.xjyl.gov.cn/upload/1982074932392591361.html
rd.xjyl.gov.cn/upload/1982074932640055296.html
rd.xjyl.gov.cn/upload/1982074932661026816.html
rd.xjyl.gov.cn/upload/1982074932728135680.html
rd.xjyl.gov.cn/upload/1982074932954628096.html
rd.xjyl.gov.cn/upload/1982074932958822400.html
rd.xjyl.gov.cn/upload/1982074933034319872.html
rd.xjyl.gov.cn/upload/1982074933306949632.html
rd.xjyl.gov.cn/upload/1982074933361475584.html
rd.xjyl.gov.cn/upload/1982074933424390144.html
rd.xjyl.gov.cn/upload/1982074933432778752.html
rd.xjyl.gov.cn/upload/1982074933508276224.html
rd.xjyl.gov.cn/upload/1982074933596356608.html
rd.xjyl.gov.cn/upload/1982074933575385088.html}
};void weakPtrSolution() {auto node1 = std::make_shared<NodeSafe>();auto node2 = std::make_shared<NodeSafe>();node1->next = node2;node2->prev = node1; // 不会增加引用计数// 可以正常析构,无内存泄漏
}void weakPtrUsage() {auto shared = std::make_shared<int>(42);std::weak_ptr<int> weak = shared;// 检查对象是否还存在if (auto locked = weak.lock()) {std::cout << "Object exists: " << *locked << std::endl;} else {std::cout << "Object has been destroyed" << std::endl;}shared.reset(); // 释放对象if (auto locked = weak.lock()) {std::cout << "Object exists: " << *locked << std::endl;} else {std::cout << "Object has been destroyed" << std::endl;}
}最佳实践总结
优先使用 unique_ptr
默认选择,性能最好
明确表达独占所有权
需要共享所有权时使用 shared_ptr
多个对象需要访问同一资源
注意避免循环引用
使用 weak_ptr 打破循环引用
观察者模式
缓存场景
使用 make_shared 和 make_unique
更安全,避免显式 new
更好的性能(make_shared)
避免使用 auto_ptr
已被废弃,使用 unique_ptr 替代
完整示例
cpp
#include <memory>
#include <iostream>
#include <vector>int main() {// unique_ptr 示例std::unique_ptr<int> unique = std::make_unique<int>(10);// shared_ptr 示例std::shared_ptr<int> shared1 = std::make_shared<int>(20);std::shared_ptr<int> shared2 = shared1;// weak_ptr 示例std::weak_ptr<int> weak = shared1;// 在容器中使用智能指针std::vector<std::shared_ptr<int>> vec;vec.push_back(std::make_shared<int>(1));vec.push_back(std::make_shared<int>(2));vec.push_back(std::make_shared<int>(3));for (const auto& ptr : vec) {std::cout << *ptr << " ";}std::cout << std::endl;return 0;
}智能指针是现代 C++ 内存管理的核心工具,正确使用可以显著提高代码的安全性和可维护性。
