C++ weak_ptr详解
在C++智能指针家族中,weak_ptr
可能是最容易被误解和忽视的一员。然而,它在解决某些特定问题(尤其是循环引用问题)时扮演着不可替代的角色。本文将全面介绍weak_ptr
的概念、用法和应用场景,帮助初学者彻底理解这个重要的工具。
weak_ptr的基本概念
weak_ptr
是C++11标准库中引入的一种智能指针,它是shared_ptr
的助手而非替代品。weak_ptr
最关键的特性是:
- 它不拥有它所指向的对象
- 它不影响对象的引用计数
- 它不能直接访问对象,必须先转换为
shared_ptr
weak_ptr
就像一个"旁观者",它可以观察shared_ptr
所管理的对象,但不参与对象生命周期的管理。
提示
你可以将weak_ptr
理解为一个对象的"弱引用",它不会阻止对象被销毁。
weak_ptr的基本用法
创建weak_ptr
weak_ptr
通常从一个shared_ptr
创建:
#include <iostream>
#include <memory>
int main() {
// 创建一个shared_ptr
std::shared_ptr<int> sp = std::make_shared<int>(42);
// 从shared_ptr创建weak_ptr
std::weak_ptr<int> wp = sp;
std::cout << "shared_ptr引用计数: " << sp.use_count() << std::endl;
return 0;
}
输出:
shared_ptr引用计数: 1
注意创建weak_ptr
后,shared_ptr
的引用计数没有增加。
使用weak_ptr
由于weak_ptr
不能直接访问所指向的对象,我 们需要先将其转换为shared_ptr
:
#include <iostream>
#include <memory>
int main() {
std::shared_ptr<int> sp = std::make_shared<int>(42);
std::weak_ptr<int> wp = sp;
// 检查weak_ptr是否过期
if (!wp.expired()) {
// 将weak_ptr转换为shared_ptr
std::shared_ptr<int> sp2 = wp.lock();
if (sp2) {
std::cout << "值: " << *sp2 << std::endl;
std::cout << "引用计数: " << sp2.use_count() << std::endl;
}
} else {
std::cout << "weak_ptr已过期" << std::endl;
}
return 0;
}
输出:
值: 42
引用计数: 2
检查weak_ptr是否过期
当weak_ptr
指向的对象已被销毁时,我们称这个weak_ptr
为"过期"(expired)的:
#include <iostream>
#include <memory>
int main() {
std::weak_ptr<int> wp;
{
auto sp = std::make_shared<int>(42);
wp = sp;
std::cout << "wp过期了吗?" << (wp.expired() ? "是" : "否") << std::endl;
} // sp离开作用域,对象被销毁
std::cout << "现在wp过期了吗?" << (wp.expired() ? "是" : "否") << std::endl;
// 尝试获取已过期的weak_ptr
if (auto sp = wp.lock()) {
std::cout << "wp有效: " << *sp << std::endl;
} else {
std::cout << "wp已过期,无法获取值" << std::endl;
}
return 0;
}
输出:
wp过期了吗?否
现在wp过期了吗?是
wp已过期,无法获取值