在C++中std::shared_ptr
可以实现多个对象共享同一块内存, 但存在循环引用
的问题. 即两个shared_ptr
互相指向对方, 导致引用计数无法被递减到0, 造成内存泄露
. 下面看一个有问题的例子:
#include <iostream>
#include <memory>
class Any {
public:
friend bool set_relationship(std::shared_ptr<Any> & p1,
std::shared_ptr<Any> & p2) {
if (!p1 || !p2) {
return false;
}
p1->m_another = p2;
p2->m_another = p1;
return true;
}
private:
std::shared_ptr<Any> m_another;
};
int main(void) {
auto p1 = std::make_shared<Any>();
auto p2 = std::make_shared<Any>();
set_relationship(p1, p2);
return 0;
}
通过valgrind
工具进行内存检查:
==1996== LEAK SUMMARY:
==1996== definitely lost: 32 bytes in 1 blocks
==1996== indirectly lost: 32 bytes in 1 blocks
==1996== possibly lost: 0 bytes in 0 blocks
==1996== still reachable: 0 bytes in 0 blocks
==1996== suppressed: 0 bytes in 0 blocks
使用shared_ptr
导致循环引用, 的确造成了内存泄露.
下面看一个使用weak_ptr
的例子:
#include <iostream>
#include <memory>
class Any {
public:
Any(int a) : m_a(a) {}
friend bool set_relationship(std::shared_ptr<Any> &p1,
std::shared_ptr<Any> &p2) {
if (!p1 || !p2) {
return false;
}
// weak_ptr重载的赋值运算符中可以接收shared_ptr对象
p1->m_another = p2;
p2->m_another = p1;
return true;
}
void show(void) { std::cout << m_a << std::endl; }
std::weak_ptr<Any> &get_ptr(void) { return m_another; }
private:
int m_a;
std::weak_ptr<Any> m_another;
};
int main(void) {
auto p1 = std::make_shared<Any>(1);
auto p2 = std::make_shared<Any>(2);
set_relationship(p1, p2);
assert(p1.use_count() == 1);
assert(p2.use_count() == 1);
p1->get_ptr().lock()->show(); // 输出: 2
return 0;
}
通过valgrind
工具进行内存检查:
==4775== HEAP SUMMARY:
==4775== in use at exit: 0 bytes in 0 blocks
==4775== total heap usage: 3 allocs, 3 frees, 72,768 bytes allocated
==4775==
==4775== All heap blocks were freed -- no leaks are possible
通过 weak_ptr
能够解决 shared_ptr
循环引用带来的内存泄
露问题. 如果觉得有帮助,可以扫描右边的微信打赏码支持一下.