weak_ptr


weak_ptr用来搭配shared_ptr,当shared_ptr实例用来构造weak_ptr实例或指定给weak_ptr时,动态配置资源的参考计数并不会增加。例如:

#include <iostream>
#include <memory>
using namespace std;

template<typename T>
struct Node {
    Node(T v) : v(v) {}
    ~Node() {
        cout << v << " deleted" << endl;
    }

    T v;
    weak_ptr<Node<T>> pre;
    weak_ptr<Node<T>> nxt;
};

weak_ptr<Node<int>> foo() {
    auto sp = make_shared<Node<int>>(10);
    weak_ptr<Node<int>> wp = sp;    

    cout << wp.expired() << endl;          // 0
    shared_ptr<Node<int>> sp2 = wp.lock();

    cout << sp2->v << endl;                // 10

    return wp;
}

int main() {
    weak_ptr<Node<int>> wp = foo();
    cout << wp.expired() << endl;          // 1

    return 0;
}

在这个范例中,sp动态配置的资源要不要删除,与wp没有关系,weak_ptr指向的资源还有没有效(是否被删除),可以透过expired来得知,若要获取资源,可以透过lock方法,如果资源仍有效,就会返回shared_ptr实例,否则返回nullptr

weak_ptr用来搭配shared_ptr,应用场合之一是解决shared_ptr形成环状的问题,例如底下的范例会因为shared_ptr形成环状,使得最后各自的资源并没有被删除:

#include <iostream>
#include <memory>
using namespace std;

template<typename T>
struct Node {
    Node(T v) : v(v) {}
    ~Node() {
        cout << v << " deleted" << endl;
    }

    T v;
    shared_ptr<Node<T>> pre;
    shared_ptr<Node<T>> nxt;
};

int main() {
    auto node1 = make_shared<Node<int>>(10);
    auto node2 = make_shared<Node<int>>(20);

    cout << node1.use_count() << endl   // 1
         << node2.use_count() << endl;  // 1

    node1->nxt = node2;
    node2->pre = node1;

    cout << node1.use_count() << endl   // 2
         << node2.use_count() << endl;  // 2   

    return 0;
}

可以看到,shared_ptr被指定给shared_ptr,会令参考计数增加,两个shared_ptr实例各自被回收时,各自的参考计数都会是一而不是零,shared_ptr各自的资源并不会被删除,若是底下程序:

#include <iostream>
#include <memory>
using namespace std;

template<typename T>
struct Node {
    Node(T v) : v(v) {}
    ~Node() {
        cout << v << " deleted" << endl;
    }

    T v;
    weak_ptr<Node<T>> pre;
    weak_ptr<Node<T>> nxt;
};

int main() {
    auto node1 = make_shared<Node<int>>(10);
    auto node2 = make_shared<Node<int>>(20);

    cout << node1.use_count() << endl   // 1
         << node2.use_count() << endl;  // 1

    node1->nxt = node2;
    node2->pre = node1;

    cout << node1.use_count() << endl   // 1
         << node2.use_count() << endl;  // 1   

    return 0;
}

shared_ptr被指定给weak_ptr,不会令参考计数增加,两个shared_ptr实例各自被回收时,各自的参考计数都会是零,shared_ptr各自的资源可以被删除。


展开阅读全文