0%

weak_ptr是如何解决循环引用的

C++11中智能指针包括三种:共享指针(shared_ptr),独占指针(unique_ptr),弱指针(weak_ptr)。

智能指针通过计数原理来实现,但在使用过程中可能会出现循环引用的问题,我们可以通过weak_ptr去解决。

出现循环引用的举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <iostream>
#include <memory>

using namespace std;

class Child;
class Parent;

class Parent {
private:
shared_ptr<Child> ChildPtr;
public:
void setChild(shared_ptr<Child> child) {
this->ChildPtr = child;
}

void doSomething() {
if (this->ChildPtr.use_count()) {

}
}

~Parent() {
}
};

class Child {
private:
shared_ptr<Parent> ParentPtr;
public:
void setPartent(shared_ptr<Parent> parent) {
this->ParentPtr = parent;
}
void doSomething() {
if (this->ParentPtr.use_count()) {

}
}
~Child() {
}
};

int main() {
weak_ptr<Parent> wpp;
weak_ptr<Child> wpc;
{
shared_ptr<Parent> p(new Parent);
shared_ptr<Child> c(new Child);
p->setChild(c);
c->setPartent(p);
wpp = p;
wpc = c;
cout << p.use_count() << endl; // 2
cout << c.use_count() << endl; // 2
}
cout << wpp.use_count() << endl; // 1
cout << wpc.use_count() << endl; // 1
return 0;
}

在如下例子中定义了两个类 Parent、Child,在两个类中分别定义另一个类的对象的共享指针,由于在程序结束后,两个指针相互指向对方的内存空间,导致内存无法释放。

使用weak_ptr解决循环引用

因为weak_ptr的作用是绑定到一个智能指针上,但不会影响该指针的计数,所以我们只需要在原本的循环引用中,令其中一环为weak_ptr即可打破这个闭环。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <iostream>
#include <memory>

using namespace std;

class Child;
class Parent;

class Parent {
private:
//shared_ptr<Child> ChildPtr;
weak_ptr<Child> ChildPtr;
public:
void setChild(shared_ptr<Child> child) {
this->ChildPtr = child;
}

void doSomething() {
//new shared_ptr
if (this->ChildPtr.lock()) {

}
}

~Parent() {
}
};

class Child {
private:
shared_ptr<Parent> ParentPtr;
public:
void setPartent(shared_ptr<Parent> parent) {
this->ParentPtr = parent;
}
void doSomething() {
if (this->ParentPtr.use_count()) {

}
}
~Child() {
}
};

int main() {
weak_ptr<Parent> wpp;
weak_ptr<Child> wpc;
{
shared_ptr<Parent> p(new Parent);
shared_ptr<Child> c(new Child);
p->setChild(c);
c->setPartent(p);
wpp = p;
wpc = c;
cout << p.use_count() << endl; // 2
cout << c.use_count() << endl; // 1
}
cout << wpp.use_count() << endl; // 0
cout << wpc.use_count() << endl; // 0
return 0;
}

为什么在访问weak_ptr所指的对象时,要先转为shared_ptr?