面试题答案
一键面试以下是使用C++ 代码示例说明std::weak_ptr
通过lock()
函数进行锁定操作,以及锁定成功和失败时的返回值情况:
#include <iostream>
#include <memory>
int main() {
// 创建一个std::shared_ptr
std::shared_ptr<int> sharedPtr = std::make_shared<int>(42);
// 创建一个std::weak_ptr指向sharedPtr
std::weak_ptr<int> weakPtr(sharedPtr);
// 尝试锁定weakPtr
std::shared_ptr<int> lockedPtr = weakPtr.lock();
if (lockedPtr) {
std::cout << "锁定成功,值为: " << *lockedPtr << std::endl;
} else {
std::cout << "锁定失败" << std::endl;
}
// 释放sharedPtr
sharedPtr.reset();
// 再次尝试锁定weakPtr
lockedPtr = weakPtr.lock();
if (lockedPtr) {
std::cout << "锁定成功,值为: " << *lockedPtr << std::endl;
} else {
std::cout << "锁定失败" << std::endl;
}
return 0;
}
在上述代码中:
- 首先创建了一个
std::shared_ptr
指向一个int
类型的对象,并将其值初始化为42
。 - 接着创建一个
std::weak_ptr
指向sharedPtr
。 - 第一次调用
weakPtr.lock()
,此时sharedPtr
仍然存在,所以锁定成功,lock()
函数返回一个有效的std::shared_ptr
,可以通过它访问对象的值。 - 然后通过
sharedPtr.reset()
释放sharedPtr
,此时int
对象的引用计数变为0,对象被销毁。 - 第二次调用
weakPtr.lock()
,由于指向的对象已经被销毁,所以锁定失败,lock()
函数返回一个空的std::shared_ptr
。
应用场景
- 解决循环引用问题:在使用
std::shared_ptr
时,如果存在循环引用,会导致内存泄漏。例如,类A和类B相互持有对方的std::shared_ptr
,这样两个对象的引用计数永远不会为0。使用std::weak_ptr
可以打破这种循环引用。比如,类A持有类B的std::weak_ptr
,当类B的std::shared_ptr
被释放后,类A的std::weak_ptr
可以通过lock()
函数尝试获取std::shared_ptr
,如果获取失败说明类B对象已经不存在。 - 缓存场景:在缓存系统中,缓存的对象可能会被其他地方释放(比如缓存淘汰策略)。缓存中可以使用
std::weak_ptr
指向对象,当需要使用缓存对象时,通过lock()
函数尝试锁定,如果锁定成功则说明对象还在,可以继续使用;如果锁定失败则需要重新获取或生成对象。