• 智能指针


    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 <memory>
    #include <iostream>
    using namespace std;
    
    int main()
    {
        unique_ptr<int> up1(new int(11));        
        unique_ptr<int> up2 = up1;        //不能通过编译
    
        cout << *up1 << endl;                //11
        unique_ptr<int> up3 = move(up1);    //现在p3是数据唯一的unique_ptr智能指针
    
        cout << *up3 << endl;                //11
        cout << *up1 << endl;                //运行时错误
        up3.reset();                        //显式释放内存
        up1.reset();                        //不会导致运行时错误
        cout << *up3 << endl;                //运行时错误
    
        shared_ptr<int> sp1(new int(22));
        shared_ptr<int> 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 up2 = up1;不能通过编译,由于up1唯一地占有了new分配的堆内存,所以up2无法共享其“所有权”。这种“所有权”仅能通过标准库的move函数来转移。unique_ptr up3 = move(up1)语句中up3通过move函数夺去了up1的“所有权”,后段使用的*up1就会出现运行时错误。

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

    weak_ptr

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

    Example:

    #include <memory>
    #include <iostream>
    using namespace std;
    
    void Check(weak_ptr<int> &wp)
    {
        shared_ptr<int> sp = wp.lock();    //转换为shared_ptr<int>
        if (sp != nullptr)
            cout << "still " << *sp << endl;
        else
            cout << "pointer is invalid." << endl;
    }
    
    int main()
    {
        shared_ptr<int> sp1(new int(22));
        shared_ptr<int> sp2 = sp1;
        weak_ptr<int> wp = sp1;    //指向shared_ptr<int>所指对象
    
        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则可用在用户需要引用计数的地方。

    新战场:https://blog.csdn.net/Stephen___Qin
  • 相关阅读:
    印象笔记和有道云笔记竞品分析
    印象笔记需求分析文档
    ES(Elasticsearch)
    java8中optional和.stream().map()
    设计模式-builder(构造器模式)
    throw与throws
    异常java.lang.NumberFormatException解决
    Spring注解
    Spring配置数据源以及hibernate
    log4j配置文件——hibernate
  • 原文地址:https://www.cnblogs.com/Stephen-Qin/p/9217620.html
Copyright © 2020-2023  润新知