C++11智能指针shared_ptr怎么使用

发布时间:2021-11-26 15:25:20 作者:iii
来源:亿速云 阅读:222

C++11智能指针shared_ptr怎么使用

在C++11标准中,引入了智能指针的概念,以帮助开发者更好地管理动态内存,避免内存泄漏和悬空指针等问题。shared_ptr 是其中一种常用的智能指针,它通过引用计数机制来管理对象的生命周期。本文将详细介绍 shared_ptr 的使用方法。

1. shared_ptr 的基本概念

shared_ptr 是一种共享所有权的智能指针,多个 shared_ptr 可以指向同一个对象,并且只有当最后一个指向该对象的 shared_ptr 被销毁或重置时,对象才会被自动删除。这种机制通过引用计数来实现,每个 shared_ptr 都会维护一个引用计数,当引用计数变为0时,对象就会被释放。

2. shared_ptr 的创建

2.1 使用 make_shared 创建

make_shared 是创建 shared_ptr 的推荐方式,它可以在一次内存分配中同时创建对象和引用计数,从而提高效率。

#include <memory>
#include <iostream>

class MyClass {
public:
    MyClass() { std::cout << "MyClass constructed\n"; }
    ~MyClass() { std::cout << "MyClass destroyed\n"; }
};

int main() {
    std::shared_ptr<MyClass> ptr = std::make_shared<MyClass>();
    return 0;
}

在上面的代码中,make_shared<MyClass>() 创建了一个 MyClass 对象,并返回一个 shared_ptr 指向该对象。当 ptr 离开作用域时,MyClass 对象会被自动销毁。

2.2 使用构造函数创建

你也可以通过 shared_ptr 的构造函数来创建智能指针,但这种方式不如 make_shared 高效,因为它需要两次内存分配(一次用于对象,一次用于引用计数)。

std::shared_ptr<MyClass> ptr(new MyClass());

2.3 使用 reset 方法

reset 方法可以用于重新分配 shared_ptr 所指向的对象,或者将其置为空。

std::shared_ptr<MyClass> ptr;
ptr.reset(new MyClass());

3. shared_ptr 的拷贝与赋值

shared_ptr 支持拷贝和赋值操作,每次拷贝或赋值都会增加引用计数。

std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
std::shared_ptr<MyClass> ptr2 = ptr1;  // 引用计数增加

在上面的代码中,ptr1ptr2 都指向同一个 MyClass 对象,引用计数为2。当 ptr1ptr2 都离开作用域时,引用计数变为0,对象被销毁。

4. shared_ptr 的引用计数

你可以通过 use_count 方法来获取当前 shared_ptr 的引用计数。

std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
std::cout << "use_count: " << ptr1.use_count() << std::endl;  // 输出 1

std::shared_ptr<MyClass> ptr2 = ptr1;
std::cout << "use_count: " << ptr1.use_count() << std::endl;  // 输出 2

5. shared_ptr 的自定义删除器

shared_ptr 允许你指定一个自定义的删除器,用于在对象被销毁时执行特定的清理操作。

void customDeleter(MyClass* ptr) {
    std::cout << "Custom deleter called\n";
    delete ptr;
}

int main() {
    std::shared_ptr<MyClass> ptr(new MyClass(), customDeleter);
    return 0;
}

在上面的代码中,当 ptr 离开作用域时,customDeleter 会被调用,执行自定义的清理操作。

6. shared_ptr 的注意事项

6.1 避免循环引用

shared_ptr 的一个常见问题是循环引用,即两个或多个 shared_ptr 互相引用,导致引用计数永远不为0,从而造成内存泄漏。为了避免这种情况,可以使用 weak_ptr 来打破循环引用。

class B;  // 前向声明

class A {
public:
    std::shared_ptr<B> b_ptr;
    ~A() { std::cout << "A destroyed\n"; }
};

class B {
public:
    std::weak_ptr<A> a_ptr;  // 使用 weak_ptr 避免循环引用
    ~B() { std::cout << "B destroyed\n"; }
};

int main() {
    std::shared_ptr<A> a = std::make_shared<A>();
    std::shared_ptr<B> b = std::make_shared<B>();
    a->b_ptr = b;
    b->a_ptr = a;
    return 0;
}

6.2 避免裸指针与 shared_ptr 混用

在使用 shared_ptr 时,应尽量避免将裸指针与 shared_ptr 混用,因为这可能导致悬空指针或重复删除的问题。

MyClass* rawPtr = new MyClass();
std::shared_ptr<MyClass> ptr1(rawPtr);
std::shared_ptr<MyClass> ptr2(rawPtr);  // 错误!会导致重复删除

6.3 避免使用 get() 方法获取裸指针

get() 方法返回 shared_ptr 所管理的裸指针,但使用这个裸指针时要非常小心,因为它不会增加引用计数,可能导致悬空指针。

std::shared_ptr<MyClass> ptr = std::make_shared<MyClass>();
MyClass* rawPtr = ptr.get();
// 不要对 rawPtr 进行 delete 操作

7. 总结

shared_ptr 是 C++11 中非常强大的工具,它通过引用计数机制自动管理对象的生命周期,极大地简化了内存管理。然而,使用 shared_ptr 时也需要注意避免循环引用和裸指针混用等问题。通过合理使用 shared_ptr,你可以编写出更安全、更高效的 C++ 代码。

推荐阅读:
  1. C++11智能指针和引用
  2. 用代码详解C++11中std::shared_ptr总结与使用

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

c++

上一篇:C++在什么时候定义枚举的底层类型

下一篇:C#如何实现基于Socket套接字的网络通信封装

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》