C++智能指针 auto_ptr shared_ptr weak_ptr

auto_ptr

auto_ptr是C++标准库中()为了解决资源泄漏的问题提供的一个智能指针类模板(注意:这只是一种简单的智能指针)

auto_ptr的实现原理其实就是RAII,在构造的时候获取资源,在析构的时候释放资源,并进行相关指针操作的重载,使用起来就像普通的指针。

对于编译器来说,智能指针实质是一个栈对象,而并非指针类型

智能指针通过构造函数获取堆内存的管理所有权,而在其生命期结束时,再通过析构函数释放由它所管理的堆内存。

所有智能指针都重载了“operator->”操作符,直接返回对象的引用,用以操作对象。访问智能指针原来的方法则使用“.”操作符

访问智能指针包含的裸指针则可以用get()函数

由于智能指针是一个对象,所以if(spObject)永远为真。要判断智能指针的裸指针是否为空,需要这样判断:if(spObject.get())

智能指针包含了reset()方法,如果不传递参数(或传递NULL),则智能指针会释放当前管理的内存。如果传递一个对象,则智能指针会释放当前对象,来管理新传入的对象。

std::auto_ptr<ClassA> pa(new ClassA);
#include<iostream>
#include<memory>
using namespace std;

class Int
{
public:
    Int(int nValue = 0) 
    {
        m_nValue = nValue;
        std::cout << "Constructor: " << m_nValue << std::endl; 
    }
    ~Int() 
    {
        std::cout << "Destructor: " << m_nValue << std::endl;
    }
    void PrintValue()
    {
        std::cout << "PrintValue: " <<m_nValue<< std::endl;
    }
    void SetValue(int nSetValue)
    {
        m_nValue = nSetValue;
    }

private:
    int m_nValue;
};

void TestAuto_Ptr1() 
{
    std::auto_ptr<Int>    spInt(new Int(10));   // 创建对象 初值为使用 10 的Int对象
    if (spInt.get())                     // 判断智能指针是否为空
    { 
        spInt->PrintValue();        // 使用operator->调用智能指针对象的函数
        spInt.get()->SetValue(20);    // 使用get()返回裸指针,然后通过裸指针调用的成员函数
        spInt->PrintValue();        // 再次打印,检验上步赋值成功
        (*spInt).SetValue(30);        // 使用operator*返回智能指针内部对象,然后用“.”调用智能指针对象中的函数
        spInt->PrintValue();        // 再次打印,表明上步赋值成功            
    }
    // !!!spInt栈对象结束生命期,随之析构堆对象Int(10),同时释放内存资源, 不用的显示的调用 delete
}

int main()
{
    TestAuto_Ptr1();
    return 0;
}

//执行结果如下:
/*
Constructor: 10
PrintValue: 10
PrintValue: 20
PrintValue: 30
Destructor: 30
*/
总结:关于std::auto_ptr的使用,请注意以下几点:

(1)尽量不要使用“operator=”(如果使用了,请不要再使用先前对象)。

(2)记住release()函数不会释放对象,仅仅归还所有权。

(3)std::auto_ptr最好不要当成参数传递(读者可以自行写代码确定为什么不能)。

(4)由于std::auto_ptr的“operator=”问题,由其管理的对象不能放入std::vector等容器中。

(5)auto_ptr存储的指针应该为NULL或者指向动态分配的内存块。

(6)auto_ptr存储的指针应该指向单一物件(是new出来的,而不是new[]出来的)。

(7)两个auto_ptr对象不会同时指向同一块内存块(要明白两个auto_ptr对象赋值会发生什么)。

shared_ptr

boost::shared_ptr是可以共享所有权的智能指针
shared_ptr非常有价值、非常重要、非常有用

#include <string>
#include <iostream>
#include <boost/shared_ptr.hpp>

class implementation
{
public:
    ~implementation() { std::cout <<"destroying implementation\n"; }
    void do_something() { std::cout << "did something\n"; }
};

void test()
{
    boost::shared_ptr<implementation> sp1(new implementation());
    std::cout<<"The Sample now has "<<sp1.use_count()<<" references\n";

    boost::shared_ptr<implementation> sp2 = sp1; // 智能指针的复制, 同事指向一个对象
    std::cout<<"The Sample now has "<<sp2.use_count()<<" references\n";

    sp1.reset();
    std::cout<<"After Reset sp1. The Sample now has "<<sp2.use_count()<<" references\n";

    sp2.reset();
    std::cout<<"After Reset sp2.\n";
}

int main()
{
    test();
    return 0;
}

sp1对implementation对象进行管理,其引用计数为1
增加sp2对implementation对象进行管理,其引用计数增加为2
sp1释放对implementation对象进行管理,其引用计数变为1
sp2释放对implementation对象进行管理,其引用计数变为0,该对象被自动删除

程序输出

扫描二维码关注公众号,回复: 5893883 查看本文章
The Sample now has 1 references
The Sample now has 2 references
After Reset sp1. The Sample now has 1 references
destroying implementation  // 此时执行了销毁函数
After Reset sp2.

boost::shared_ptr指针sp1和sp2**同时拥有了implementation对象的访问权限,且当sp1和sp2都释放对该对象的所有权时,其所管理的的对象的内存才被自动释放**。在共享对象的访问权限同时,也实现了其内存的自动管理。

特点: boost::shared_ptr可以共享对象的所有权

weak_ptr

weak_ptr是为了配合shared_ptr而引入的一种智能指针,它更像是shared_ptr的一个助手而不是智能指针,因为它不具有普通指针的行为,没有重载operator*和->,它的最大作用在于协助shared_ptr工作,像旁观者那样观测资源的使用情况.

eak_ptr被设计为与shared_ptr共同工作,可以从一个shared_ptr或者另一个weak_ptr对象构造,获得资源的观测权。但weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加

使用weak_ptr的成员函数use_count()可以观测资源的引用计数, weak_ptr可以使用一个非常重要的成员函数lock()从被观测的shared_ptr获得一个可用的shared_ptr对象,

参考资料

weak_ptr 类: https://msdn.microsoft.com/zh-cn/library/bb982126.aspx

猜你喜欢

转载自blog.csdn.net/Fourier_Legend/article/details/82226091