C++11智能指针的前因后果

本文详细介绍了C++11中的智能指针,包括为何弃用auto_ptr,unique_ptr和shared_ptr的使用方法,以及weak_ptr的注意事项。文章强调了智能指针在解决内存管理问题中的重要作用,特别是如何避免野指针、重复释放和内存泄漏。此外,还讨论了shared_ptr在多线程环境下的考虑和weak_ptr在解决循环引用中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0 前言 

据说用过java的人都说java好,很大一部分是java里没有指针的概念,并提供自动垃圾机制,而C/C++语言经常会被内存的释放问题搞得头疼。

全局对象在程序启动时分配,在程序结束时销毁。对于局部自动对象,当我们进入其定义所在的程序块时被创建,在离开块时销毁。局部stratic对象在第一次使用前分配,在程序结束时销毁。对于自动和static对象外,C++还支持动态分配对象。动态分配的对象的生存期与它们在哪儿创建是无关的,只有当显示地被释放时,这些对象才会销毁。

动态对象的正确分配/释放被证明是编程中极其容易出现错误的地方,从语言层次上归纳为以下问题:

(1)野指针(空悬指针):一些内存单元已经被释放,之前指向它的指针却还在被使用。这些内存有可能被运行的系统重新分配给程序使用,从而导致了无法预测的错误。解决措施:delete后,将nullptr赋予指针,表明指针不指向任何对象。但可能有多个指针指向相同的内存,在delete内存后重置指针只对这个指针有效,对其他任何仍指向(已释放的)的内存的指针式没有作用。

int *p(new int(42)  // p指向动态内存
auto q = p;         // p和q指向相同的内存
delete p;           // p和q均变为无效
p = nullptr;        // 指出p不再绑定任何对象

(2)重复释放:程序试图去释放已经释放过的内存单元,或者释放已经被重新分配过的内存单元,就会导致重复释放错误。通常重复释放内存会导致C/C++运行时系统打印出大量错误及诊断信息。解决措施:new与delete配合使用,new几次,delete几次,但这实际要求很高。

(3)内存泄漏:不再需要使用的内存单元如果没有被释放就会导致内存泄漏。如果程序不断重复进行这类操作,将会导致内存占用剧增。解决措施:查找内存泄漏时非常困难的。(后面再提如何检测内存泄漏)

// eg01
void create()
{
    int *p = new int[100];
    // 这里忘记释放内存后,则退出函数后无法释放内存
}


// eg02
int& create()
{
    int *p = new int[100];
    return *p;
}

int main()
{
    int &p = create();   // 这里必须要用引用来接收返回值,不然无法释放内存
    delete &p; 
}

// eg02的编程风格非常不好,及其容易产生内存泄漏

综上,为了避免以上及其容易出现的问题(并且这些问题还非常难以查找和解决),C++提供了智能指针,如auto_ptr(在C++11中已被弃用、C++17已被移除)、shared_ptr、unique_ptr,weak_ptr。

但是,任何时候都要用智能指针来代替原始指针吗,也就是不要显示/直接去管理内存吗?(我在知乎上看到了这么一个问题,底下回答意见不一,我个人水平不够就不发表意见了,贴个地址有兴趣的可以去看下:

c++是否应避免使用普通指针,而使用智能指针(包括shared,unique,weak)?

 

再谈下占栈内存/静态内存/堆内存,因为后面智能指针的原理就是基于栈。

静态内存用来保存局部static对象、类static数据成员以及定义在任何函数之外的变量。栈内存用来保存定义在函数内的非static对象。分配在静态或栈内存中的对象由编译器自动创建和释放。对于栈对象(也称自动对象),仅在其定义的程序块运行时才存在,当到达块末尾时销毁;static对象在使用之前分配,在程序结束时销毁。

除了静态内存和栈内存,每个程序还拥有一个内存池。这部分内存被称为自由空间或堆。程序用堆来存储动态分配对象,动态对象的生命周期由程序控制,所以要显式销毁它们。

而智能指针则结合了栈对象的安全性(栈对象离开作用域后会自动销毁)和堆内存的灵活性。

 

1 智能指针简介

智能指针是一个模板,因此我们创建一个智能指针时,必须提供额外的信息,指针可以指向的类型。

shared_ptr<string> p1;    

默认初始化的智能指针中保存了一个空指针。智能指针的使用方式和普通指针类似(一般怎么使用原始指针就怎么使用只能指针)。

c++11提供了两种智能指针来管理动态对象。shared_ptr允许多个指针指向同一个对象;unique_ptr则”独占“所指向的对象。C++11还定义了一个名为weak_ptr的伴随类,它是一种弱引用,指向shared_ptr所管理的对象。这三种类型都定义在memory头文件中。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值