C++ 智能指针的使用

一、动态指针说明
C++中主要使用new和delete来分配和释放内存,但有时候我们常常因为忘记delete而造成内存泄漏的问题。于是C++中出现了智能指针模板类来管理动态内存,以避免因为我们“遗忘”而造成内存泄漏的问题。C++中标准的智能指针有4个:auto_ptr、shared_ptr、unique_ptr、weak_ptr。这4个智能指针的头文件都在memory中。

1、auto_ptr:是比较老的一个智能指针类了,auto_ptr要求对它所拥有的指针完全占用,所以两个auto_ptr指针不能同时拥有一个一般指针,当前占有一般指针的auto_ptr会剥夺之前智能指针的所有权,如果此时再操作之前的智能指针就会发生错误。auto_ptr智能指针不能作为函数参数按值传递,而应该作为引用传递但又不能预测函数体内是否发生所有权的转移。auto_ptr在进行赋值和复制时会进行一些特殊操作,所以它不能作为C++STL中容器的元素。由于auto_ptr这些缺陷导致它已经被新的C++11标准抛弃啦。取而代之的是新标准中的shared_ptr、unique_ptr、weak_ptr这三种智能指针。
官方方法链接

2、shared_ptr:
<1>与auto_ptr独占相比,允许多个指针拥有一个对象。
<2>默认创建的指针是一个空指针,解引用一个智能指针返回它指向的对象。
<3>每个shared_ptr都有一个关联的引用计数器。当我们拷贝一个shared_ptr时计数器的值会递增;当我们给它赋一个新值或者销毁它时计数器会递减。
<4>自动销毁所管理的对象。由于智能指针都是类,它有自己的析构函数,当它的引用计数器变为0时会自动调用析构函数销毁该对象。
<5>和new结合使用,默认的shared_ptr是一个空指针,可以使用new来给它初始化,但不可以直接初始化。例如:shared_ptr p1(new int(100))可以,shared_ptrp2 = new int(100)不可以。
官方方法链接

3、unique_ptr:
<1>与shared_ptr不同,unique_ptr是独占所拥有的对象。所以当unique_ptr被销毁时它指向的对象也会被销毁。
<2>shared_ptr提供了一个make_shared的标准函数库来返回shared_ptr,而unique_ptr则没有类似的函数。当我们定义一个unique_ptr时需要使用new来为其直接初始化。
<3>由于<1>的原因,它不支持普通的拷贝和复制操作。
<4>unique_ptr提供了release和reset方法将指针的所有权转移。例如:
unique_ptrp1(new string(“ISMILELI”));
unique_ptrp2(p1.release()); // 将p1置空并将所有权给p2
unique_ptrp3(new string(“hello world”));
p2.reset(p3.release()); // reset释放了p2原来的内存并把p3的所有权转移给了p2。
<5>release切断了unique_ptr和它所管理的对象之间的联系。release的返回值一般用来初始化另一个智能指针或者给另一个智能指针赋值。如果给一个普通的指针赋值的话就需要我们自己手动释放该普通指针的内存才行。
官方方法链接

4、weak_ptr:
<1>它是一种弱引用,指向shared_ptr的管理对象,不能直接访问对象。
<2>weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数器。
<3>weak_ptr和shared_ptr同时指向一个对象时,当shared_ptr销毁时,该对象就会被释放,这就是它弱的特点。
<4>weak_ptr提供了直接访问对象的函数lock,此函数会返回一个共享的shared_ptr对象,此时它就有了和shared_ptr类似的功能。
官方方法链接

二、测试代码

#include <iostream>
#include <memory>

using namespace std;

int main(int argc, char *argv[])
{
    shared_ptr<int> pInt = make_shared<int>(702);
    shared_ptr<string> pStr = make_shared<string>("ISMILELI");
    if(!pInt /*&& pInt->empty()*/)
    {
        cout << "pInt is empty!" << endl;
    }
    else
    {
        cout << "pInt.use_count=" << pInt.use_count() << "\n*pInt=" << *pInt << endl;
    }
    if(pStr->empty())
    {
        cout << "pStr is empty!" << endl;
    }
    else
    {
        cout << "pStr.use_count=" << pStr.use_count() << "\n*pStr=" << *pStr << endl;
    }
    shared_ptr<int> pInt2(new int(419));
    if(pInt2)
        cout << "pInt2=" << *pInt2 << endl;
    pInt2.reset(new int(100));
    cout << "pInt2.reset()=" << *pInt2 << endl;
    cout << "==============test unique_ptr===============" << endl;
    unique_ptr<int> pIntUnique(new int(1000));
    cout << "pIntUnique:" << *pIntUnique << endl;
    unique_ptr<int> pIntUnique2(pIntUnique.release());
    if(!pIntUnique)
    {
        cout << "pIntUnique is release!" << endl;
    }
    if(pIntUnique2)
    {
        cout << "pIntUnique2:" << *pIntUnique2 << endl;
    }
    unique_ptr<int[]> pIntUnique3(new int[10]);
    //pIntUnique3.release();
    for(int i=0; i<10; i++)
    {
        pIntUnique3[i] = i;
        cout << " pIntUnique3["<< i << "]=" << pIntUnique3[i];
    }
    cout << endl;
    pIntUnique3.release();
    cout << "==============test weak_ptr===============" << endl;
    auto pShared = make_shared<int>(702);
    weak_ptr<int> pIntWeak(pShared);
    cout << "pShared use_count=" << pShared.use_count() << " *pShared="<< *pShared << endl;
    shared_ptr<int> pWShared = pIntWeak.lock();
    cout << "pShared use_count=" << pShared.use_count() << " *pWShared="<< *pWShared <<endl;
    cout << "Hello World!" << endl;
    return 0;
}

结果:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/toby54king/article/details/81271947
今日推荐