智能指针

综合编程 2018-06-23

C++98中的智能指针通过一个模板类 auto_ptr
来实现, new
操作符返回的指针可以交由它来管理,程序员不用再显式的调用 delete
,这在一定程度上避免了堆内存忘记释放的问题;

不过 auto_ptr
有一些缺点,比如拷贝时返回一个左值,不能调用delete[]等


C++11中废弃了 auto_ptr
,改用 unique_ptr、shared_ptr、weak_ptr
等智能指针来自动回收堆分配对象,使内存管理更安全,智能指针的使用场景也变得更全面。

unique_ptr和shared_ptr

unique_ptr是唯一性智能指针,无法进行复制,但是可以移动。而shared_ptr是共享性智能指针,采用引用计数,可以拷贝和移动,移动时引用计数不会变化。

Example

#include 
#include 
using namespace std;

int main()
{
    unique_ptr up1(new int(11));        
    unique_ptr up2 = up1;        //不能通过编译

    cout << *up1 << endl;                //11
    unique_ptr up3 = move(up1);    //现在p3是数据唯一的unique_ptr智能指针

    cout << *up3 << endl;                //11
    cout << *up1 << endl;                //运行时错误
    up3.reset();                        //显式释放内存
    up1.reset();                        //不会导致运行时错误
    cout << *up3 << endl;                //运行时错误

    shared_ptr sp1(new int(22));
    shared_ptr sp2 = sp1;

    cout << *sp1 << endl;    //22
    cout << *sp2 << endl;    //22

    sp1.reset();
    cout << *sp2 << endl;    //22
}

//编译选项:g++ -std=c++11 unique_share.cpp

上例中,指针调用reset成员时,智能指针都可能释放其拥有的堆内存。

从代码中可以看出,unique_ptr和shared_ptr在对所占内存的共享上还是有一定区别的。

unique_ptr不能与其他unique_ptr类型的指针共享所指对象的内存。比如unique_ptr

而shared_ptr允许多个智能指针共享地“拥有”同一堆分配对象的内存。与unique_ptr不同的是,一旦一个shared_ptr指针放弃了“所有权”,其他的shared_ptr对对象内存的引用并不会受到影响。上例中的sp2很好说明了这个状况,sp1调用了reset成员,只是使得引用计数的降低,不会导致堆内存的释放。只有在引用计数归零时,shared_ptr才会真正地释放所占有的堆内存的空间。

weak_ptr

弱智能指针,通常指向一个共享性智能指针,当要使用所指向的共享性智能指针时,使用lock方法获取,并验证共享性智能指针的有效性。

Example:

#include 
#include 
using namespace std;

void Check(weak_ptr &wp)
{
    shared_ptr sp = wp.lock();    //转换为shared_ptr
    if (sp != nullptr)
        cout << "still " << *sp << endl;
    else
        cout << "pointer is invalid." << endl;
}

int main()
{
    shared_ptr sp1(new int(22));
    shared_ptr sp2 = sp1;
    weak_ptr wp = sp1;    //指向shared_ptr所指对象

    cout << *sp1 << endl;    //22
    cout << *sp2 << endl;    //22
    Check(wp);                //still 22

    sp1.reset();            
    cout << *sp2 << endl;    //22
    Check(wp);                //still 22

    sp2.reset();
    Check(wp);                //pointer is invalid

    return 0;
}

//编译选项:g++ -std=c++11 weak.cpp

上例中定义了2个shared_ptr——sp1和sp2,而weak_ptr wp同样指向该对象内存。当sp1和sp2有效时,调用wp的lock(),check会输出still 22。当分别调用sp1和sp2的reset()时,会导致堆内存对象的引用计数降为0。一旦引用计数归0,shared_ptr

整个过程中,只有shared_ptr参与了引用计数, 而weak_ptr没有影响其指向的内存的引用计数
。因此可以验证shared_ptr指针的有效性。

简单情况下,程序员用unique_ptr代替以前使用auto_ptr就可以使用C++11中的智能指针。而shared_ptr及weak_ptr则可用在用户需要引用计数的地方。

博客园精华区

责编内容by:博客园精华区 (源链)。感谢您的支持!

您可能感兴趣的

游戏程序员成长编年史(1) 前些天和HR团队一起录了一个校园招聘实习生相关的节目,聊聊游戏程序员做些什么,如何准备面试,有什么建议。聊得不够尽兴,觉得还是写几篇文章展开说一下会比...
Zeal – An Offline Documentation Browser For Develo... The other day I was searching for Vim editor cheatsheets on the web. A quick go...
What Developers Should Know from Microsoft Build It used to be that I could easily ignore the news coming from Redmond. Sure, ...
AWS streamlines cloud services for JavaScript deve... Amazon Web Services has developed a declarative JavaScript library, AWS Amplify,...
程序员小知识:JS数组常用方法操作 今天igeek手册与大家分享的是: JS数组常用方法操作 ,希望大家看完能有所收获哦~ 1、push 添加最后一项 在数组末尾添加...