C++ 智能指针与容器
外观
概述[编辑 | 编辑源代码]
C++智能指针是一种自动管理动态内存的RAII(Resource Acquisition Is Initialization)对象,而容器是存储和管理对象集合的数据结构。将智能指针与标准库容器结合使用,可以安全高效地处理动态分配对象的生命周期问题,避免内存泄漏和悬空指针等问题。
智能指针主要包括:
std::unique_ptr
(独占所有权)std::shared_ptr
(共享所有权)std::weak_ptr
(避免循环引用)
智能指针与容器的结合[编辑 | 编辑源代码]
为什么需要结合使用?[编辑 | 编辑源代码]
容器(如std::vector
、std::map
)通常存储原始指针时需手动释放内存,而智能指针能自动释放资源。结合使用可:
- 简化内存管理
- 避免容器元素的内存泄漏
- 支持异常安全
基本用法示例[编辑 | 编辑源代码]
以下示例展示std::vector
与std::unique_ptr
的结合:
#include <iostream>
#include <memory>
#include <vector>
class MyClass {
public:
MyClass(int val) : value(val) {
std::cout << "Constructed: " << value << std::endl;
}
~MyClass() {
std::cout << "Destroyed: " << value << std::endl;
}
void print() const { std::cout << "Value: " << value << std::endl; }
private:
int value;
};
int main() {
std::vector<std::unique_ptr<MyClass>> vec;
// 添加元素
vec.push_back(std::make_unique<MyClass>(10));
vec.push_back(std::make_unique<MyClass>(20));
// 访问元素
for (const auto& ptr : vec) {
ptr->print();
}
// 自动释放内存
return 0;
}
输出:
Constructed: 10 Constructed: 20 Value: 10 Value: 20 Destroyed: 20 Destroyed: 10
所有权转移问题[编辑 | 编辑源代码]
std::unique_ptr
不可复制,但可通过移动语义转移所有权:
std::vector<std::unique_ptr<MyClass>> vec1;
auto ptr = std::make_unique<MyClass>(30);
vec1.push_back(std::move(ptr)); // 所有权转移
高级应用场景[编辑 | 编辑源代码]
共享所有权的容器[编辑 | 编辑源代码]
当需要多个容器共享对象时,使用std::shared_ptr
:
std::vector<std::shared_ptr<MyClass>> sharedVec1;
std::vector<std::shared_ptr<MyClass>> sharedVec2;
auto sharedObj = std::make_shared<MyClass>(99);
sharedVec1.push_back(sharedObj);
sharedVec2.push_back(sharedObj); // 共享所有权
避免循环引用[编辑 | 编辑源代码]
使用std::weak_ptr
打破循环引用:
struct Node {
std::shared_ptr<Node> next;
std::weak_ptr<Node> prev; // 避免循环引用
};
性能考量[编辑 | 编辑源代码]
内存开销对比[编辑 | 编辑源代码]
类型 | 额外开销 |
---|---|
std::unique_ptr |
无(仅存储指针) |
std::shared_ptr |
控制块(引用计数等) |
std::weak_ptr |
同shared_ptr
|
容器选择建议[编辑 | 编辑源代码]
- 优先使用
std::unique_ptr
(性能最优) - 需要共享时再用
std::shared_ptr
- 关联容器(如
std::map
)的键避免用智能指针
实际案例[编辑 | 编辑源代码]
场景:对象池管理[编辑 | 编辑源代码]
使用std::vector<std::unique_ptr<Texture>>
管理游戏资源:
class TexturePool {
private:
std::vector<std::unique_ptr<Texture>> textures;
public:
void load(const std::string& path) {
textures.push_back(std::make_unique<Texture>(path));
}
// 其他管理接口...
};
场景:多线程安全共享[编辑 | 编辑源代码]
线程安全的共享数据容器:
std::vector<std::shared_ptr<const Data>> getSnapshot() {
std::lock_guard<std::mutex> lock(dataMutex);
return currentData; // 返回共享数据的副本
}
常见问题[编辑 | 编辑源代码]
Q1: 能否在容器中存储auto_ptr
?[编辑 | 编辑源代码]
页面模块:Message box/ambox.css没有内容。
C++17已移除 auto_ptr ,绝对不要使用! |
Q2: 如何排序智能指针容器?[编辑 | 编辑源代码]
提供自定义比较器:
std::sort(vec.begin(), vec.end(),
[](const std::unique_ptr<MyClass>& a, const std::unique_ptr<MyClass>& b) {
return a->value < b->value;
});
总结[编辑 | 编辑源代码]
- 优先选择
std::unique_ptr
+ 容器组合 - 共享所有权时使用
std::shared_ptr
- 注意容器的操作可能影响智能指针的生命周期