在C++的内存管理体系中,手动使用new和delete分配释放内存很容易出现忘记释放、重复释放等问题,智能指针的出现就是为了解决这些痛点。unique_ptr是C++11引入的智能指针类型,它遵循独占所有权的原则,同一时间只能有一个unique_ptr指向特定的堆内存对象,当unique_ptr离开作用域时,会自动释放所管理的对象,从根源上减少内存泄漏的可能。

unique_ptr的基本创建方式
创建unique_ptr最常用的方式是使用std::make_unique函数,这是C++14引入的安全创建方式,能避免一些潜在的内存泄漏问题。当然也可以直接通过new的方式构造,不过更推荐优先使用make_unique。
下面是两种创建方式的代码示例:
#include <memory>
#include <iostream>
int main() {
// 使用make_unique创建unique_ptr,管理一个int类型的堆对象
std::unique_ptr<int> ptr1 = std::make_unique<int>(10);
// 直接通过new构造unique_ptr,不推荐但语法合法
std::unique_ptr<int> ptr2(new int(20));
std::cout << *ptr1 << std::endl; // 输出10
std::cout << *ptr2 << std::endl; // 输出20
return 0;
}
unique_ptr的常用操作
unique_ptr提供了一些常用的成员函数和操作符,方便开发者使用它管理内存:
- 解引用操作:使用*操作符可以获取unique_ptr管理的对象,使用->操作符可以访问对象的成员。
- get()函数:返回指向管理对象的原始指针,注意不要轻易手动delete这个指针,否则会导致重复释放。
- release()函数:释放unique_ptr对对象的所有权,返回原始指针,此时unique_ptr变为空指针,不再管理该对象。
- reset()函数:释放当前管理的对象,如果传入新的指针,会管理新的对象。
下面是这些操作的代码示例:
#include <memory>
#include <iostream>
class Test {
public:
void show() {
std::cout << "Test show called" << std::endl;
}
};
int main() {
std::unique_ptr<Test> ptr = std::make_unique<Test>();
// 使用->访问对象成员
ptr->show();
// 使用*解引用获取对象
Test& obj = *ptr;
obj.show();
// get获取原始指针
Test* rawPtr = ptr.get();
rawPtr->show();
// release释放所有权
Test* releasedPtr = ptr.release();
// 此时ptr为空,不再管理对象,需要手动释放releasedPtr
delete releasedPtr;
// reset重置管理对象
std::unique_ptr<int> numPtr = std::make_unique<int>(5);
numPtr.reset(new int(10)); // 释放原来的5,管理新的10
std::cout << *numPtr << std::endl; // 输出10
numPtr.reset(); // 释放管理的对象,numPtr变为空
return 0;
}
unique_ptr的所有权转移规则
unique_ptr的核心特性是独占所有权,因此它不支持拷贝构造和拷贝赋值,只能进行所有权转移。转移之后,原来的unique_ptr会变为空,不再拥有对象的管理权。
所有权转移可以通过std::move实现,也可以在一些场景下隐式转移,比如作为函数返回值返回时。
下面是所有权转移的代码示例:
#include <memory>
#include <iostream>
// 函数返回unique_ptr,隐式转移所有权
std::unique_ptr<int> createInt() {
return std::make_unique<int>(100);
}
int main() {
std::unique_ptr<int> ptr1 = std::make_unique<int>(50);
// 使用std::move转移所有权,转移后ptr1变为空
std::unique_ptr<int> ptr2 = std::move(ptr1);
if (!ptr1) {
std::cout << "ptr1 is null after move" << std::endl;
}
std::cout << *ptr2 << std::endl; // 输出50
// 接收函数返回的unique_ptr,所有权转移
std::unique_ptr<int> ptr3 = createInt();
std::cout << *ptr3 << std::endl; // 输出100
return 0;
}
unique_ptr的常见使用场景
unique_ptr适合用在需要独占资源的场景,比如:
- 管理堆上创建的单个对象,替代手动的new和delete操作。
- 作为函数的返回值,返回堆对象的所有权,避免返回原始指针导致的内存泄漏。
- 在容器中存储动态对象,比如
std::vector<std::unique_ptr<T>>,此时容器拥有这些对象的所有权。
下面是容器中存储unique_ptr的示例:
#include <memory>
#include <vector>
#include <iostream>
int main() {
std::vector<std::unique_ptr<int>> vec;
// 向容器中添加unique_ptr,需要使用std::move转移所有权
vec.push_back(std::make_unique<int>(1));
vec.push_back(std::make_unique<int>(2));
vec.push_back(std::make_unique<int>(3));
for (const auto& ptr : vec) {
std::cout << *ptr << " ";
}
// 输出1 2 3
std::cout << std::endl;
// 容器销毁时,会自动释放所有unique_ptr管理的对象
return 0;
}
使用unique_ptr的注意事项
使用unique_ptr时需要注意以下几点:
- 不要将unique_ptr管理的原始指针赋值给普通指针后手动delete,否则会导致unique_ptr析构时重复释放。
- 不要对同一个原始指针创建多个unique_ptr,会导致重复释放的问题。
- 如果需要共享所有权,应该使用
std::shared_ptr而不是unique_ptr。
unique_ptr是C++内存管理中非常实用的工具,掌握它的使用方法能有效提升代码的安全性和健壮性,减少内存相关的问题。
unique_ptr智能指针C++内存管理RAII修改时间:2026-07-17 23:33:30