shared_ptr
最大的问题是不能解决循环依赖问题,所以有时候必须使用 weak_ptr
来解决问题。比如构造双向链表的时候,如果前驱和后继都使用 shared_ptr
,就会造成内存泄漏。
#include <iostream>
#include <memory>
using namespace std;
class node {
public:
node(int val):
_next(nullptr),
_data(val)
{}
~node() { cout << _data << ": I am deleted" << endl; }
void setNext(shared_ptr<node> next) { _next = next; }
void setPrior(shared_ptr<node> prior) { _prior = prior; }
shared_ptr<node> getNext() { return _next; }
private:
node();
shared_ptr<node> _next;
weak_ptr<node> _prior;
int _data;
};
int main() {
auto n1 = make_shared<node>(node(1));
{ // this colon makes `p` local
shared_ptr<node> p = n1;
for (int i = 2; i < 7; i++) {
auto n = make_shared<node>(node(i));
p->setNext(n);
n->setPrior(p);
p = n;
}
}
shared_ptr<node> n2 = make_shared<node>(node(9));
{
shared_ptr<node> p = n2;
int i = 0;
do {
auto n = make_shared<node>(node(i + 10));
n->setPrior(p);
p->setNext(n);
p = n;
i++;
} while (i < 5);
}
cout << "------------" << endl;
n1->getNext()->getNext()->getNext()->setNext(n2);
cout << "------------" << endl;
n2->setPrior(n1->getNext()->getNext()->getNext());
cout << "------------" << endl;
}
输出
1: I am deleted
2: I am deleted
3: I am deleted
4: I am deleted
5: I am deleted
6: I am deleted
9: I am deleted
10: I am deleted
11: I am deleted
12: I am deleted
13: I am deleted
14: I am deleted
------------
5: I am deleted
6: I am deleted
------------
------------
1: I am deleted
2: I am deleted
3: I am deleted
4: I am deleted
9: I am deleted
10: I am deleted
11: I am deleted
12: I am deleted
13: I am deleted
14: I am deleted
其中前 16 和 914 是 make_shared 过程中产生的零时对象析构造成的。
如果把上面 weak_ptr<node> _prior
改为 shared_ptr<node> _prior
,输出变为:
1: I am deleted
2: I am deleted
3: I am deleted
4: I am deleted
5: I am deleted
6: I am deleted
9: I am deleted
10: I am deleted
11: I am deleted
12: I am deleted
13: I am deleted
14: I am deleted
------------
------------
------------