在C++现代开发中,unique_ptr是最常用的智能指针之一,它能保证动态资源在离开作用域时自动释放。但当我们需要把多个unique_ptr集中管理时,往往会想到使用STL容器。由于unique_ptr禁止拷贝,只能移动,把它和STL容器结合使用有一些必须掌握的技巧。

为什么unique_ptr不能直接拷贝进容器
unique_ptr通过删除拷贝构造函数和拷贝赋值运算符来保证独占所有权。如果尝试用push_back拷贝一个unique_ptr对象,编译器会直接报错。例如下面的代码是无法通过编译的:
#include <memory>
#include <vector>
int main() {
std::unique_ptr<int> p = std::make_unique<int>(10);
std::vector<std::unique_ptr<int>> vec;
// vec.push_back(p); // 错误:unique_ptr不可拷贝
return 0;
}
使用move语义转移所有权
正确的做法是使用std::move把所有权移入容器。此后原unique_ptr变为空,不再指向资源。
#include <memory>
#include <vector>
#include <iostream>
int main() {
std::vector<std::unique_ptr<int>> vec;
auto p = std::make_unique<int>(20);
vec.push_back(std::move(p)); // 所有权转移
if (!p) {
std::cout << "原指针已为空" << std::endl;
}
return 0;
}
使用emplace_back简化写法
如果资源在插入时才创建,可以直接用emplace_back在容器内构造unique_ptr,避免临时对象移动:
#include <memory>
#include <vector>
int main() {
std::vector<std::unique_ptr<int>> vec;
vec.emplace_back(std::make_unique<int>(30));
return 0;
}
在map等关联容器中使用
对于std::map,同样只能通过移动或就地构造来保存unique_ptr作为值:
#include <memory>
#include <map>
#include <string>
int main() {
std::map<std::string, std::unique_ptr<int>> m;
m["a"] = std::make_unique<int>(1);
m.emplace("b", std::make_unique<int>(2));
return 0;
}
遍历与删除元素
遍历容器时应该使用引用,避免试图拷贝unique_ptr:
#include <memory>
#include <vector>
#include <iostream>
int main() {
std::vector<std::unique_ptr<int>> vec;
vec.emplace_back(std::make_unique<int>(5));
for (const auto& p : vec) {
std::cout << *p << std::endl;
}
// 删除单个元素,资源自动释放
vec.erase(vec.begin());
return 0;
}
从函数返回装有unique_ptr的容器
由于容器本身可以移动,返回局部容器对象是安全的,编译器通常会进行移动或返回值优化:
#include <memory>
#include <vector>
std::vector<std::unique_ptr<int>> create() {
std::vector<std::unique_ptr<int>> v;
v.emplace_back(std::make_unique<int>(100));
return v; // 容器移动,内部unique_ptr所有权随容器转移
}
int main() {
auto data = create();
return 0;
}
注意事项总结
- 不要尝试拷贝unique_ptr,始终使用std::move或emplace系列接口。
- 从容器取用元素时,若需转移所有权,同样使用std::move。
- 容器析构时会依次释放其中的unique_ptr,无需手动delete。
- 避免把unique_ptr作为key存入无序容器,其不可拷贝特性会带来不便。
掌握上述技巧后,你就能在STL容器中安全高效地管理独占资源,写出更现代、更健壮的C++程序。
unique_ptrSTL容器move语义修改时间:2026-07-28 01:39:26