晦涩难懂?五分钟带你了解C++中的智能指针 妈妈再也不用担心我忘记释放内存辣!

引入

裸指针是C++中最基本的指针类型。它们直接存储内存地址,并允许通过指针访问和操作内存中的数据

然而,手动管理指针会带来复杂性和潜在的错误 内存泄漏、悬空指针和双重释放等问题会导致程序崩溃或产生难以排查的错误

C++11引入的智能指针旨在解决这些问题。智能指针的本质就是封装的裸指针自动管理对象的生命周期,从而减少手动内存管理带来的风险

在C++标准库中提供了三种主要的智能指针:std::unique_ptrstd::shared_ptr std::weak_ptr

1.std::unique_ptr 独占指针

std::unique_ptr 是一种独占所有权的智能指针,一个std::unique_ptr只能独占其所指向的对象,同一时间只有一个指针拥有该对象。当 std::unique_ptr 被销毁时,它所管理的对象也会被自动销毁。std::unique_ptr 不支持复制操作,但支持移动操作,这使得它非常适合用于管理动态分配的资源

具体操作:

  创建:使用std::make_unique

  访问:使用*ptr或者ptr.get()获取原始指针访问

  转移所有权:使用std::move

代码演示:

#include <iostream>
#include <memory>//引入智能指针的头文件

int main(void) {
    std::unique_ptr<int> ptr1(new int(10));    // 创建一个指向整数10的unique_ptr
    std::cout << "ptr1 的值: " << *ptr1 << std::endl;

    // std::unique_ptr<int> ptr2 = ptr1;       // 错误:unique_ptr不能被拷贝
    std::unique_ptr<int> ptr2 = std::move(ptr1); // 正确:通过std::move进行所有权转移
    if(ptr1 == nullptr) {
        std::cout << "ptr1 为空" << std::endl;
    }
    std::cout << "ptr2 的值: " << *ptr2 << std::endl;//打印10
}

2.std::shared_ptr共享指针

std::shared_ptr是一种共享所有权的智能指针,多个std::shared_ptr可以共享同一个对象。通过引用计数来管理对象的生命周期,当最后一个指向该对象的shared_ptr被销毁时,该对象才会被销毁。

具体操作:

  创建:使用std::make_shared

  访问:使用*ptr或者ptr.get()获取原始指针访问

  引用计数:使用use_count方法

代码演示:

#include <iostream>
#include <memory>//引入智能指针头文件

int main(void) {
    std::shared_ptr<int> ptr1(new int(10));    // 创建一个指向整数10的shared_ptr
    std::cout << "ptr1 的值: " << *ptr1 << std::endl;

    std::shared_ptr<int> ptr2 = ptr1;          // 可复制 ptr2与ptr1共享同一个对象
    std::cout << "ptr2 的值: " << *ptr2 << std::endl;

    std::cout << "ptr1 的引用计数: " << ptr1.use_count() << std::endl;
    std::cout << "ptr2 的引用计数: " << ptr2.use_count() << std::endl;//都是2

}

3.std::weak_ptr小帮手

std::weak_ptr是一种弱引用智能指针,它不会影响对象的引用计数,专门用来于解决std::shared_ptr之间的循环引用问题 。所以std::weak_ptr必须与std::shared_ptr一起使用

什么是循环引用?

 两个共享指针相互指向对方 导致引用计数无法归0 最终导致程序崩溃

代码示例:

#include <iostream>
#include <memory>

class B; 

class A {
public:
    std::shared_ptr<B> ptrB;
};

class B {
public:
    std::shared_ptr<A> ptrA;
};

int main(void) {
    {

        std::shared_ptr<A> a = std::make_shared<A>();
        std::shared_ptr<B> b = std::make_shared<B>();

        a->ptrB = b;
        b->ptrA = a;
    }
}

所以为了解决这个问题专门引入的weak_ptr 

将class A和class B中的任意一个shared_ptr改成weak_ptr即可解决

#include <iostream>  
#include <memory>  
  
class B;  
  
class A {  
public:  
    std::shared_ptr<B> ptrB;  
};  
  
class B {  
public:  
    std::weak_ptr<A> ptrA; // 使用 weak_ptr 来避免循环引用  
};  
  
int main() {  
    {  
        std::shared_ptr<A> a = std::make_shared<A>();  
        std::shared_ptr<B> b = std::make_shared<B>();  
  
        a->ptrB = b;  
        b->ptrA = a;  
  
        // a 和 b 的引用计数会开始减少。  
        // 由于 B 类中使用的是 weak_ptr,所以不会阻止 A 类对象的释放。  
    }  
    // 在此处,a 和 b 都会被正确释放,不再存在循环引用。  
}

总结

为了避免忘记释放内存导致一系列的问题 智能指针能用则用

这篇文章讲的只是智能指针皮毛中的皮毛,智能指针还有很多内置函数没有提到,有兴趣可以通过其他途径了解更多相关知识

  • 14
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值