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

举报
人才程序员 发表于 2024/09/14 18:09:04 2024/09/14
【摘要】 @TOC 前言在 C++ 编程中,智能指针是一种重要的工具,用于自动管理动态分配的内存。std::shared_ptr 是 C++11 引入的智能指针之一,它允许多个 std::shared_ptr 实例共享对同一个对象的所有权。std::shared_ptr 通过引用计数机制来管理内存的生命周期,确保对象在最后一个 std::shared_ptr 被销毁时才释放。 为什么使用 std::s...

@TOC


前言

在 C++ 编程中,智能指针是一种重要的工具,用于自动管理动态分配的内存。std::shared_ptr 是 C++11 引入的智能指针之一,它允许多个 std::shared_ptr 实例共享对同一个对象的所有权。std::shared_ptr 通过引用计数机制来管理内存的生命周期,确保对象在最后一个 std::shared_ptr 被销毁时才释放。


为什么使用 std::shared_ptr

  • 共享所有权std::shared_ptr 允许多个指针共享对同一个对象的所有权,适用于需要多个实体引用同一对象的场景。
  • 自动内存管理:智能指针自动管理对象的生命周期,避免了内存泄漏的问题。
  • 引用计数:内置的引用计数机制确保对象在所有 std::shared_ptr 实例都不再使用时才被释放。

std::shared_ptrstd::unique_ptr 的区别

  • 所有权管理

    • std::unique_ptr:独占所有权,确保同一时间只有一个智能指针拥有对象的所有权,不能被复制,只能移动。
    • std::shared_ptr:允许多个智能指针共享同一个对象的所有权,通过引用计数机制来管理对象的生命周期。
  • 引用计数

    • std::unique_ptr:没有引用计数,简单高效。
    • std::shared_ptr:使用引用计数来管理对象的生命周期,较为复杂但支持共享所有权。

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

构造函数

  • 默认构造函数

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

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

    std::shared_ptr(const std::shared_ptr& other);
    
    std::shared_ptr<int> p1(new int(20));
    std::shared_ptr<int> p2(p1);  // 拷贝构造
    
  • 移动构造函数

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

成员函数

  • reset

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

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

    long use_count() const noexcept;
    
    std::shared_ptr<int> p1(new int(70));
    std::shared_ptr<int> p2 = p1;
    std::cout << "Use count: " << p1.use_count() << std::endl;  // 输出引用计数
    
  • operator*

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

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

如果有多个 std::shared_ptr 指向同一内存

std::shared_ptr 允许多个智能指针实例共享对同一个对象的所有权。引用计数会随着 std::shared_ptr 实例的创建和销毁而增加或减少。当最后一个 std::shared_ptr 实例被销毁时,管理的对象才会被释放。

std::shared_ptr<int> p1(new int(90));
std::shared_ptr<int> p2 = p1;  // 共享所有权

std::cout << "Use count: " << p1.use_count() << std::endl;  // 输出引用计数

p1.reset();  // 释放 p1 的所有权
std::cout << "Use count after reset p1: " << p2.use_count() << std::endl;  // 输出引用计数

p2.reset();  // 释放 p2 的所有权,对象将被销毁

示例代码

下面的示例展示了 std::shared_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::shared_ptr<int> p1;

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

    // 使用拷贝构造函数
    std::shared_ptr<int> p3(p2);
    std::cout << "p3: " << *p3 << std::endl;

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

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

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

    // 使用 use_count 函数
    std::cout << "Use count of p5: " << p5.use_count() << std::endl;

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

    // 演示多个 shared_ptr
    std::shared_ptr<int> p7(new int(50));
    std::shared_ptr<int> p8 = p7;  // 共享所有权
    std::cout << "Use count: " << p7.use_count() << std::endl;
    p7.reset();  // 释放 p7 的所有权
    std::cout << "Use count after reset p7: " << p8.use_count() << std::endl;
    p8.reset();  // 释放 p8 的所有权,对象将被销毁

    return 0;
}

总结

std::shared_ptr 是一个强大的智能指针,用于管理动态分配的内存,并允许多个指针共享同一对象的所有权。通过引用计数机制,std::shared_ptr 确保对象在最后一个指针被销毁时才释放,避免了内存泄漏和悬空指针的问题。了解 std::shared_ptr 的构造函数和操作函数,有助于在需要共享对象所有权的场景中更安全、有效地管理内存。

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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