关键词:c++11智能指针、循环引用
C++ 11的新特性中引入了三种智能指针,来自动化地管理内存资源:unique_ptr、weak_ptr和shared_ptr。
shared_ptr通过引用计数的方式管理内存,当进行拷贝或赋值操作时,每个shared_ptr都会记录有多少个其他的shared_ptr指向相同的对象,当引用计数为0时,内存将被自动释放。
auto p = make_shared<int>(10); // 创建一个名为p的shared_ptr,指向一个取值为10的int型对象,这个数值10的引用计数为1,只有p
auto q(p); // 创建一个名为q的shared_ptr,并用p初始化,此时p和q指向同一个对象,此时数值10的引用计数为2
当对shared_ptr赋予新值,或被销毁时,引用计数会递减。
auto r = make_shared<int>(20); // 创建一个名为r的shared_ptr,指向一个取值为20的int型对象,这个数值20的引用计数为1,只有r
r = q; // 对r赋值,让r指向数值10。此时数值10的引用计数加1为3,数值20的引用计数减1位0,数值20的内存将被自动释放
通常情况下shared_ptr可以正常运转,但是在循环引用的场景下,shared_ptr无法正确释放内存。循环引用,顾名思义,A指向B,B指向A,在表示双向关系时,是很可能出现这种情况的。
为了打破循环引用,选择在双向循环链表中使用 shared_ptr
和 weak_ptr
的组合。std::weak_ptr
是一种不增加引用计数的智能指针,它用于观察一个由 std::shared_ptr
管理的对象,但不会影响对象的生命周期。通过使用 std::weak_ptr
,可以打破循环引用,同时仍然能够访问对象。shared_ptr
用于管理 next
指针,确保后继节点的生命周期被正确管理;weak_ptr
用于管理 prev
指针,打破循环引用。
template<typename Key, typename Value>
class ListNode
{
private:
Key key_;
Value value_;
size_t accessCount_; // 访问次数
std::weak_ptr<ListNode<Key, Value>> prev_; // 改为weak_ptr打破循环引用
std::shared_ptr<ListNode<Key, Value>> next_;
public:
ListNode(Key key, Value value)
: key_(key)
, value_(value)
, accessCount_(1)
{}
// 提供必要的访问器
Key getKey() const { return key_; }
Value getValue() const { return value_; }
void setValue(const Value& value) { value_ = value; }
size_t getAccessCount() const { return accessCount_; }
void incrementAccessCount() { ++accessCount_; }
};