一篇搞懂C++ STL 智能指针std::unique_ptr


前言

在现代 C++ 编程中,内存管理是一个至关重要的方面。std::unique_ptr 是 C++11 引入的智能指针之一,它用于管理动态分配的对象,确保对象在适当的时候被销毁,防止内存泄漏。std::unique_ptr 是一种独占所有权的智能指针,这意味着同一时间只有一个 std::unique_ptr 实例可以拥有某个对象的所有权。


为什么使用 std::unique_ptr

  • 自动内存管理std::unique_ptr 可以自动释放其管理的对象,避免了手动删除的麻烦。
  • 独占所有权std::unique_ptr 确保在同一时间内只有一个指针拥有对象的所有权,从而防止了双重释放和悬空指针的问题。
  • 性能优越std::unique_ptr 轻量且高效,适合用于需要动态分配内存的场景。

std::unique_ptr 的构造函数和操作函数

构造函数
  • 默认构造函数

    std::unique_ptr();
    
    std::unique_ptr<int> p;  // 创建一个空的 unique_ptr
    
  • 构造函数(原始指针)

    explicit std::unique_ptr(T* ptr);
    
    std::unique_ptr<int> p(new int(10));  // 使用原始指针构造 unique_ptr
    
  • 移动构造函数

    std::unique_ptr(std::unique_ptr&& other) noexcept;
    
    std::unique_ptr<int> p1(new int(20));
    std::unique_ptr<int> p2(std::move(p1));  // 移动构造
    

成员函数

  • reset

    void reset(T* ptr = nullptr);
    
    std::unique_ptr<int> p(new int(30));
    p.reset(new int(40));  // 释放旧对象并拥有新对象
    
  • release

    T* release();
    
    std::unique_ptr<int> p(new int(50));
    int* rawPtr = p.release();  // 释放拥有权并返回原始指针
    delete rawPtr;  // 手动删除原始指针
    
  • get

    T* get() const noexcept;
    
    std::unique_ptr<int> p(new int(60));
    int* rawPtr = p.get();  // 获取原始指针
    
  • operator*

    T& operator*() const;
    
    std::unique_ptr<int> p(new int(70));
    std::cout << *p << std::endl;  // 访问管理的对象
    
  • operator->

    T* operator->() const;
    
    struct MyClass {
        void display() const { std::cout << "Hello" << std::endl; }
    };
    std::unique_ptr<MyClass> p(new MyClass());
    p->display();  // 访问对象的成员函数
    

操作多个 std::unique_ptr

std::unique_ptr 不能直接共享所有权。如果需要多个智能指针管理同一个对象,必须使用 std::shared_ptr。以下代码示例演示了如何操作和转移 std::unique_ptr 的所有权:

std::unique_ptr<int> p1(new int(80));
std::unique_ptr<int> p2 = std::move(p1);  // p1 的所有权转移到 p2

if (!p1) {
    std::cout << "p1 is empty" << std::endl;
}
if (p2) {
    std::cout << "p2 owns the object with value: " << *p2 << std::endl;
}

示例代码

下面的示例展示了 std::unique_ptr 的各种构造函数和操作函数的用法:

#include <iostream>
#include <memory>

struct MyClass {
    MyClass(int v) : value(v) {}
    int value;
    void display() const { std::cout << "Value: " << value << std::endl; }
};

int main() {
    // 使用默认构造函数
    std::unique_ptr<int> p1;

    // 使用原始指针构造函数
    std::unique_ptr<int> p2(new int(10));
    std::cout << "p2: " << *p2 << std::endl;

    // 使用移动构造函数
    std::unique_ptr<int> p3(std::move(p2));
    if (!p2) {
        std::cout << "p2 is now empty" << std::endl;
    }

    // 使用 reset 函数
    p3.reset(new int(20));
    std::cout << "p3: " << *p3 << std::endl;

    // 使用 release 函数
    int* rawPtr = p3.release();
    std::cout << "Released raw pointer value: " << *rawPtr << std::endl;
    delete rawPtr;  // 手动删除

    // 使用 get 函数
    std::unique_ptr<MyClass> p4(new MyClass(30));
    MyClass* rawPtrClass = p4.get();
    rawPtrClass->display();

    // 使用 operator* 和 operator->
    std::unique_ptr<MyClass> p5(new MyClass(40));
    std::cout << "p5 value: " << p5->value << std::endl;
    (*p5).display();

    return 0;
}

总结

std::unique_ptr 是一个功能强大的智能指针,提供了对动态分配内存的独占所有权管理。它自动释放所管理的对象,避免了内存泄漏,并确保同一时间只有一个 std::unique_ptr 拥有对象的所有权。通过掌握 std::unique_ptr 的构造函数和操作函数,能够更安全和高效地管理动态内存。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

人才程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值