使用智能指针装入stl容器能自动管理资源生命周期,避免内存泄漏和重复释放。1. shared_ptr适合共享所有权,引用计数确保资源在最后使用后释放,应优先使用make_shared构造,避免循环引用;2. unique_ptr适用于独占所有权场景,性能更优,只能通过移动操作传递,不可复制;3. 容器复制时shared_ptr会增加引用计数,而unique_ptr禁止复制,扩容时两者均不会导致内存泄漏;4. 实际使用中需根据所有权需求选择合适类型,并注意深拷贝、循环引用等问题。

在使用 C++ 的 STL 容器时,如果容器中存放的是普通指针(raw pointer),很容易因为复制、释放时机不一致而导致内存泄漏或重复释放的问题。而将智能指针(如
std::shared_ptr和
std::unique_ptr)用于 STL 容器,可以有效避免这些问题。

为什么要用智能指针装进 STL 容器?
STL 容器(比如
vector、
map、
list等)在进行拷贝、扩容、删除元素等操作时,会频繁地构造和析构内部对象。如果里面存的是原始指针,容器本身不会自动管理这些指针指向的资源,这就容易出问题。

用智能指针代替原始指针,可以让容器内的每个元素都自动负责资源的生命周期管理:
std::shared_ptr
:适合多个容器或对象共享同一个资源的情况。std::unique_ptr
:强调独占所有权,适用于不需要共享资源的场景,更高效也更安全。
这样,即使容器被复制、元素被删除,也不用担心手动释放内存的问题。

如何正确使用 shared_ptr 放入容器?
当你希望多个地方都能持有同一个对象的所有权时,可以用
shared_ptr。例如:
std::vector<std::shared_ptr<MyClass>> vec; vec.push_back(std::make_shared<MyClass>());
几点注意事项:
- 不要手动 new 后再传进去,推荐使用
make_shared
,效率更高。 - 多个容器之间传递同一个
shared_ptr
是安全的,引用计数机制保证了资源只会在最后一个引用消失后释放。 - 避免循环引用,否则会导致内存无法释放。
举个例子,如果你有两个类互相持有对方的
shared_ptr,就可能造成内存泄露。解决办法是其中一个使用
weak_ptr。
unique_ptr 在容器中的使用技巧
如果你确定某个对象只能由一个容器拥有,那么应该优先使用
unique_ptr。它比
shared_ptr更轻量,性能更好。
使用方式也很简单:
std::vector<std::unique_ptr<MyClass>> vec; vec.push_back(std::make_unique<MyClass>());
但要注意:
unique_ptr
不能直接复制,所以容器里的元素只能通过移动语义操作。- 容器支持移动操作没问题,但在涉及拷贝操作的函数(比如某些算法)时需要特别小心。
比如下面这个写法是不行的:
auto copy = vec; // 编译错误!unique_ptr 不可复制
但你可以这样做:
auto movedVec = std::move(vec); // OK,移动而不是复制
容器复制与内存安全的几个细节
当容器里放的是智能指针时,虽然不再担心内存泄漏,但有些细节还是容易忽略:
-
shared_ptr 的复制行为:每次复制容器时,里面的每个
shared_ptr
都会增加引用计数。这不是大问题,但需要注意逻辑上是否真的需要共享。 - unique_ptr 的不可复制性:尝试复制容器会编译失败,这其实是一种保护机制,防止误操作。
-
容器扩容时的行为:无论是
shared_ptr
还是unique_ptr
,容器扩容时都会调用构造函数和析构函数,但不会导致内存泄漏。
举个实际例子:
std::vector<std::shared_ptr<int>> v; v.push_back(std::make_shared<int>(10)); auto v2 = v; // OK,引用计数变为2
此时两个容器都指向同一个
int对象,修改会影响彼此。如果你不希望这样,那就要考虑深拷贝或者改用
unique_ptr。
基本上就这些
把智能指针放进 STL 容器,说到底就是为了让资源管理更清晰、更安全。选择
shared_ptr还是
unique_ptr,取决于你对所有权的需求。只要理解它们的行为差异,并注意一些常见陷阱,就能写出既简洁又不容易出错的代码。
基本上就这些,不复杂但容易忽略。










