C++11 中新增了一种智能指针类型 unique_ptr,它是一种独占式的智能指针,用于管理动态分配的对象,并确保在其生命周期结束时正确释放资源。在使用 unique_ptr 时,指针指向的资源只能被一个 unique_ptr 持有,当 unique_ptr 被销毁时,它所指向的对象也被自动释放。
unique_ptr 的设计思想是“资源所有权的独占”,因此它的构造和析构函数都被设计为模板函数,可以自动地匹配任意类型的对象。与 shared_ptr 不同,unique_ptr 不需要维护引用计数,因此它的内存开销更小,性能更高。
unique_ptr 的使用方式与原始指针类似,可以通过重载运算符 * 和 -> 来访问指向的对象,也可以使用 get() 函数来获取指向的原始指针。与 shared_ptr 类似,unique_ptr 也可以通过移动语义来转移所有权,即将一个 unique_ptr 赋值给另一个 unique_ptr 时,被赋值的 unique_ptr 所指向的对象会转移所有权给新的 unique_ptr,被赋值的 unique_ptr 变为 null。
下面是一个示例程序,演示了 unique_ptr 的基本用法:
#include <IOStream>
#include <memory>
class MyClass {
public:
MyClass() {
std::cout << "MyClass constructor" << std::endl;
}
~MyClass() {
std::cout << "MyClass destructor" << std::endl;
}
void hello() {
std::cout << "Hello, unique_ptr!" << std::endl;
}
};
int main() {
std::unique_ptr<MyClass> ptr(new MyClass); // 构造 unique_ptr,指向动态分配的 MyClass 对象
ptr->hello(); // 使用 -> 运算符访问 MyClass 对象的成员函数
(*ptr).hello(); // 使用 * 运算符访问 MyClass 对象的成员函数
std::unique_ptr<MyClass> ptr2(std::move(ptr)); // 将 ptr 的所有权转移给 ptr2
if (!ptr) {
std::cout << "ptr is null" << std::endl;
}
ptr2->hello();
return 0;
}
当 unique_ptr 被销毁时,它所指向的对象也被自动销毁。在示例程序中,第一个 unique_ptr 的所有权被转移给第二个 unique_ptr,因此第一个 unique_ptr 变为 null。当第二个 unique_ptr 被销毁时,它所指向的 MyClass 对象也被自动销毁。
// 使用 std::make_unique 创建 unique_ptr 对象
std::unique_ptr<int> p1 = std::make_unique<int>(10);
// 使用 new 创建 unique_ptr 对象
std::unique_ptr<int> p2(new int(20));
std::unique_ptr<int> p(new int(30));
p.reset(); // 将 p 的指针设置为 nullptr,释放原来指向的内存
{
std::unique_ptr<int> p(new int(40));
// unique_ptr 对象超出作用域,内存自动释放
}
std::unique_ptr<int> p1(new int(50));
std::unique_ptr<int> p2(std::move(p1)); // 将 p1 对象转移给 p2 对象
std::unique_ptr<int> p(new int(60));
int* p_int = p.get(); // 获取 p 对象所指向的内存的指针
需要注意的是,get() 函数返回的是裸指针,不具有 unique_ptr 对象的智能指针功能。因此在使用 get() 函数返回的裸指针时需要注意内存管理的问题。
除了以上几点之外,还应该注意以下几点: