智能指针std::unique_ptr,std::shared_ptr和std::weak_ptr enable_shared_from_this

目录

1 C++中有哪些智能指针 它们的适用场景是什么 并分别举例

2 当所有std::shared_ptr都被销毁时,即使还有std::weak_ptr指向对象,对象也会被删除。那么再使用std::weak_ptr访问时内存会崩溃吗

3 enable_shared_from_this的适用场景 并举例


记录下智能指针和enable_shared_from_this的学习
1 C++中有哪些智能指针 它们的适用场景是什么 并分别举例

在C++中,有三种主要的智能指针:std::unique_ptr,std::shared_ptr和std::weak_ptr。它们都在<memory>头文件中定义。

1. std::unique_ptr:这是一种独占所有权的智能指针,也就是说,在任何时候,只能有一个std::unique_ptr指向给定的对象。当std::unique_ptr离开其作用域时,它将删除其所指向的对象。这种智能指针非常适合在你需要确保对象在出现异常或正常执行路径结束时被删除的情况下使用。#include <memory>

void function() {

    std::unique_ptr<int> ptr(new int(5));

    // do something with ptr

} // ptr is automatically deleted here


2. std::shared_ptr:这是一种共享所有权的智能指针。多个std::shared_ptr可以指向同一个对象,对象只有在最后一个指向它的std::shared_ptr被销毁时才会被删除。这种智能指针适合在你需要在多个所有者之间共享对象的情况下使用。

#include <memory>

std::shared_ptr<int> global_ptr;

void function() {

    std::shared_ptr<int> local_ptr(new int(5));

    global_ptr = local_ptr; // both local_ptr and global_ptr now own the int

} // local_ptr is destroyed, but the int is not deleted because global_ptr still owns it

3. std::weak_ptr:这是一种不拥有所有权的智能指针。它是对std::shared_ptr的一种“弱”引用,不会增加std::shared_ptr的引用计数。当所有std::shared_ptr都被销毁时,即使还有std::weak_ptr指向对象,对象也会被删除。这种智能指针适合在你需要避免std::shared_ptr的循环引用问题的情况下使用。

#include <memory>

std::weak_ptr<int> global_weak_ptr;

void function() {

    std::shared_ptr<int> local_ptr(new int(5));

    global_weak_ptr = local_ptr; // global_weak_ptr is a weak reference to the int

} // local_ptr and the int are deleted, even though global_weak_ptr still points to the int


以上就是C++中的三种智能指针及其适用场景和示例。 

2 当所有std::shared_ptr都被销毁时,即使还有std::weak_ptr指向对象,对象也会被删除。那么再使用std::weak_ptr访问时内存会崩溃吗

不会。当你试图通过std::weak_ptr访问已经被删除的对象时,C++不会导致内存崩溃。相反,std::weak_ptr提供了一种安全的方式来检查它所引用的对象是否还存在。

你可以通过调用std::weak_ptr::lock方法来获取一个std::shared_ptr。如果std::weak_ptr所引用的对象还存在(也就是说,还有至少一个std::shared_ptr指向它),那么这个方法将返回一个新的std::shared_ptr指向该对象。如果对象已经被删除,那么这个方法将返回一个空的std::shared_ptr。

这是一个例子:

#include <memory>

#include <iostream>

std::weak_ptr<int> global_weak_ptr;

void function() {

    std::shared_ptr<int> local_ptr(new int(5));

    global_weak_ptr = local_ptr;

}

int main() {

    function();

    std::shared_ptr<int> ptr = global_weak_ptr.lock();

    if (ptr) {

        std::cout << "Object still exists!\n";

    } else {

        std::cout << "Object has been deleted!\n";

    }

    return 0;

}


在这个例子中,当我们在main函数中调用global_weak_ptr.lock()时,local_ptr已经离开了其作用域并被销毁,所以global_weak_ptr.lock()返回一个空的std::shared_ptr,并且我们在控制台上看到的消息是"Object has been deleted!"。

所以,尽管std::weak_ptr可能会指向一个已经被删除的对象,但是你可以通过使用std::weak_ptr::lock方法来安全地检查对象是否还存在,而不会导致内存崩溃。 

3 enable_shared_from_this的适用场景 并举例

std::enable_shared_from_this是一个模板类,它允许你从任何对象(该对象已经被一个std::shared_ptr管理)中安全地获取一个std::shared_ptr。这在你需要传递当前对象的std::shared_ptr给其他函数或者类时非常有用。

例如,假设你有一个类,该类的某个成员函数需要将当前对象的std::shared_ptr传递给其他函数。在没有std::enable_shared_from_this的情况下,你可能会尝试这样做:

#include <memory>

class Foo {

public:

    void bar() {

        std::shared_ptr<Foo> self(new Foo(*this)); // Bad: creates a new control block!

        otherFunction(self);

    }

};


这段代码有一个问题:它创建了一个新的std::shared_ptr,这个std::shared_ptr有自己的控制块(包含引用计数等信息)。这意味着self和任何已经存在的std::shared_ptr(可能已经管理这个对象)是完全独立的。当self被销毁时,它会尝试删除对象,即使可能还有其他std::shared_ptr指向它。

std::enable_shared_from_this解决了这个问题。当一个类继承自std::enable_shared_from_this,它就可以使用shared_from_this函数安全地获取一个std::shared_ptr,而不会创建新的控制块。这是一个例子:

#include <memory>

class Foo : public std::enable_shared_from_this<Foo> {

public:

    void bar() {

        std::shared_ptr<Foo> self = shared_from_this(); // Good: shares the control block!

        otherFunction(self);

    }

};


在这个例子中,self和任何已经存在的std::shared_ptr共享同一个控制块。当self被销毁时,它不会删除对象,除非它是最后一个指向对象的std::shared_ptr。

注意,shared_from_this只能在至少有一个std::shared_ptr已经管理对象的情况下使用。如果没有std::shared_ptr管理对象,调用shared_from_this将抛出std::bad_weak_ptr异常。

这就是std::enable_shared_from_this的适用场景和示例。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值