码迷,mamicode.com
首页 > 编程语言 > 详细

C++11新特性之智能指针

时间:2015-12-06 01:47:46      阅读:208      评论:0      收藏:0      [点我收藏+]

标签:

  1、shared_ptr:一种计数指针,被指向的对象在引用计数为0时删除。它表示共享的所有权(负责对象的删除销毁)。需要包含<memory>,下同。

// 定义删除器
struct Deleter
{
public:
    void operator() (Base *p)
    {
        cout << "[deleter called]" << endl;
        delete p;
    }
};

int main()
{
    shared_ptr<Base> p1(new Base, Deleter());
    {
        shared_ptr<Base> p2(p1);    // 这里p1/p2的use_count()为2
        {
            shared_ptr<Base> p3(p2);    // 这里p1/p2/p3的use_count()为3
        }    // p1/p2的use_count()变为2
    }    // p1的use_count()变为1

    p1.reset();    // 无参的reset()将使p1变为空(就像默认构造时一样)

    // p1的use_count()变为0且上面的new Base被删除/析构

    return 0;
}

  以下用法是错误的:

// 错误1:既使用shared_ptr,又自己管理原生指针。原生指针被重复析构
int *p = new int(9);
shared_ptr<int> sp1(p);
delete p;

// 错误2:多个shared_ptr均从同一个原生指针构造。原生指针被重复析构
// 多个shared_ptr管理同一个原生指针,则后续的shared_ptr都应直接或间接(通过weak_ptr)从第一个构造
int *q = new int(10);
shared_ptr<int> sp2(q);
shared_ptr<int> sp3(q);

  有时候,需要在类的成员函数里面获取到“指向”当前对象的shared_ptr(然后把它传递给其他函数)。此时,只需要继承enable_shared_from_this,即可在成员函数中使用shared_from_this()获取到shared_ptr。示例:

class Foo;

class Bar
{
public:
    void test(shared_ptr<Foo> sp);
};

class Foo : public enable_shared_from_this<Foo>
{
public:
    void test();
    void print();
};

void Bar::test(shared_ptr<Foo> sp)
{
    // 此时sp.use_count()为3
    sp -> print();
}

void Foo::test()
{
    // 若换成shared_ptr<Foo> sp = shared_ptr<Foo>(this);会出错
    // 这相当于使用一个原生指针分别构造两个shared_ptr,会造成重复释放的问题
    shared_ptr<Foo> sp = shared_from_this();  // 此时sp.use_count()为2
    Bar bar;
    bar.test(sp);
    // 此时sp.use_count()为2
}

void Foo::print() { cout << "in Foo::print" << endl; }

int main()
{
    shared_ptr<Foo> sp1(new Foo);
    sp1 -> test();
    // 此时sp1.use_count()为1

    // !!!错误用法,抛出bad_weak_ptr异常!!!
    // 原因(参考boost的enable_shared_from_this.hpp):enable_shared_from_this有一个weak_ptr类型的成员,
    // 它只能由shared_ptr通过enable_shared_from_this的一个成员函数赋值(故使用以下方式时,该成员为空),
    // shared_from_this()正是通过该成员“获取”到shared_ptr
    Foo *fp = new Foo;
    fp -> test();
    delete fp; 
}

  2、weak_ptr:Weak shared pointer

int main()
{
    shared_ptr<int> sp1(new int(10));

    // 可以用shared_ptr/weak_ptr构造weak_ptr
    // weak_ptr拥有资源的访问权,但没有所有权(不会增加引用计数)
    weak_ptr<int> wp(sp1);  // wp和sp1的use_count()均为1

    if (!wp.expired())
    {
        // lock():从weak_ptr“获取”一个可用的shared_ptr对象
        shared_ptr<int> sp2 = wp.lock();  // wp和sp1的use_count()均为2
        *sp2 = 100;
    }

    // 此时wp和sp1的use_count()均为1

    return 0;
}

  expired():检查weak_ptr对象是否失效(为空或已经没有shared_ptr和它一起观测某个资源)。和空weak_ptr一样,失效的weak_ptr不能用于还原出shared_ptr(lock())。expired()和use_count()==0返回相同的结果,但效率更高。示例:

weak_ptr<int> wp;    // 此时wp.expired()为1

shared_ptr<int> sp1(new int);
wp = sp1;
shared_ptr<int> sp2 = wp.lock();

// 此时wp.expired()为0

sp2.reset();    // 此时wp.expired()为0
sp1.reset();    // 此时wp.expired()为1

  另外,weak_ptr没有重载*和->运算符,不能像普通指针一样使用(要借助lock(),参考第一个例子中的sp2)。

  shared_ptr还有“环状引用”的问题,也需要使用weak_ptr来规避,如下例:

class parent;
class children;
typedef shared_ptr<parent> parent_ptr;  // 改为typedef weak_ptr<parent> parent_ptr;方可避免“环状引用”的问题
typedef shared_ptr<children> children_ptr;  // 改为typedef weak_ptr<children> children_ptr;方可避免“环状引用”的问题

class parent
{
public:
    children_ptr children;
};

class children
{
public:
    parent_ptr parent;
};

int main()
{
    shared_ptr<parent> father(new parent);
    shared_ptr<children> son(new children);
    father -> children = son;
    son -> parent = father;  // father和son的use_count()均为2,程序退出时没有调用parent和children的析构函数!!!

    return 0;
}

  3、unique_ptr:

  1)在了解unique_ptr之前,先来回顾一下auto_ptr。

  auto_ptr:Automatic Pointer(自C++11起已弃用)。

  auto_ptr对象对它管理的指针拥有所有权,即负责其内存释放(释放时机:auto_ptr对象销毁时)。

  和shared_ptr一样,用同一个原生指针初始化多个auto_ptr对象会导致重复释放内存的错误。

class Base
{
public:
    Base() {cout << "in Base" << endl;}
    ~Base() {cout << "in ~Base" << endl;}
    void test() {cout << "in test" << endl;}
};

int main()
{
    auto_ptr<int> ap1(new int);
    // 基本操作
    *ap1 = 10;
    int *p = ap1.get();  // *p == 10
    auto_ptr<Base> ap2(new Base);
    ap2 -> test();

    auto_ptr<Base> ap3 = ap2; // 赋值或“复制”构造时会转移所有权(故不能用于STL容器中):ap2.get()变成NULL
    ap3 -> test();

    auto_ptr<Base> ap4(new Base);
    Base *bp = ap4.release();  // ap4.get()变成NULL。释放所有权,不再对之前管理的指针(的内存)负责。返回之前管理的指针
    delete bp;

    auto_ptr<Base> ap5(new Base);
    ap5.reset(); // “显式”销毁/析构其指向的对象。可设置指向新的对象

    return 0;
}

 

  参考资料:

  http://www.cplusplus.com

 

 

不断学习中。。。

C++11新特性之智能指针

标签:

原文地址:http://www.cnblogs.com/hanerfan/p/5022733.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!