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

举报
人才程序员 发表于 2024/09/14 18:08:50 2024/09/14
【摘要】 @TOC 前言在现代 C++ 编程中,内存管理是一个至关重要的方面。std::unique_ptr 是 C++11 引入的智能指针之一,它用于管理动态分配的对象,确保对象在适当的时候被销毁,防止内存泄漏。std::unique_ptr 是一种独占所有权的智能指针,这意味着同一时间只有一个 std::unique_ptr 实例可以拥有某个对象的所有权。 为什么使用 std::unique_pt...

@TOC


前言

在现代 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 的构造函数和操作函数,能够更安全和高效地管理动态内存。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。