智能指针 02

继前一篇:

shared_pr会出现循环以来造成悬挂指针。另外一个问题则是:必须确保某个对象只被一组shared pointer拥有。示例一个错误代码:

int * p = new int;
shared_ptr<int> sp1(p);
shared_ptr<int> sp2(p);     //ERROR:two shared pointers manage allocated int

问题在于sp1和sp2都拥有释放权,这会导致两次delete。因此应该直接在创建对象和资源的时候即刻设置smart pointer:

shared_ptr<int> sp1(new int);
shared_ptr<int> sp2(sp1);

这个问题可能间接发生,根据上一节的例子,准备为Person引入一个成员函数,用来建立“从kid指向parent” 的reference 及其反向reference:

shared_ptr<Person> mom(new Person(name + "'s mom"));
shared_ptr<Person> dad(new Person(name + "'s dad"));
shared_ptr<Person> kid(new Person(name, mom, dad));
kid->setParentsAndTheirKids(mom, dad);

//下面是一个错误的直观版本

class Person{
public:
    //....
    void setParentAndTheirKids(shared_ptr<Person> m = nullptr,
                               shared_ptr<Person> f = nullptr) {
         mother = m;
         father = f;
         if(m != nullptr){
            m->kids.push_back(shared_ptr<Perrson>(this));}   //ERROR
         if(f != nllptr){
            f->kids.push_back(shared_ptr<Person>(this));}    //ERROR
    //....
}
};

问题出在this的那个shared pointer 的建立。之所以那么做是为了设置mother 和 father两个成员的kids。但是为了那么做,需要一个shared pointer指向kid,而我们没有 。然而,根据this建立一个新的shared pointer不能解决问题,因为这么一来就是开启了新的拥有者团队(a new group of owners)。

对付这个问题的办法之一就是,将指向kid的那个shared pointer传递为第三实参。但c++标准库提供了另外一个选项:class std::enable_shared_from_this<>   。

    你可以从class std::enable_shared_from_this<> 派生自己的class,表现出被shared pointer管理的对象,做法是将class 名称当做template是实参传入。

    然后可以使用一个派生的成员函数 shared_from_this() 建立一个源自this的正确shared_ptr。

class Person : public  std::enable_shared_from_this<Person>{
public:
    //....
    void setParentAndTheirKids(shared_ptr<Person> m = nullptr,
                               shared_ptr<Person> f = nullptr) {
         mother = m;
         father = f;
         if(m != nullptr){
            m->kids.push_back(shared_from_this());}   //Ok
         if(f != nllptr){
            f->kids.push_back(shared_from_this());}    //OK
    //....
}
};

但shared_form_this 不能放在构造函数中,因为在Person构造结束之前,shared_ptr本身被存放在Person的基类中,也就是enable_shared_from_this<>内部的一个private成员中。所以,在构造期间,绝对无法建立shared pointer的循环引用。

猜你喜欢

转载自www.cnblogs.com/gardenofhu/p/9288400.html
今日推荐