C++ 中的弱指针

C++ weak_ptr是一个标准库组件。它用于存储对由shared_ptr标准库指针控制的任何对象的弱引用,该指针用于最终将weak_ptr转换为shared_ptr。最终从weak_ptr创建的shared_ptr用于访问引用的对象。在转换为shared_ptr后,weak_ptr就失去了永远保留的能力,表明它只是暂时存在。不建议在授予对引用对象的访问权限之前先访问weak_ptr 。

语法:
template< class T > class weak_ptr;  

根据 C++ weak_ptr函数的语法,弱指针控制的类型用于作为T 类提供的参数。

C++的weak_ptr是如何操作的?
高级语言中的每个指针主要用于引用对象,然后以组织良好的方式访问数组中可用的元素。类似的情况也适用于 C++ 的weak_ptr。在整个类模板中描述了weak_ptr的工作流程:

  • 最初用于引用对象的weak_ptr并不是实际的指针,因为在对象引用和赋值方面它被视为临时指针。
  • 然而,一旦weak_ptr获得了对share_ptr的最终控制或权限,对象访问和引用就变得简单而高效。
  • 这种协调和共享以及在weak_ptr和share_ptr之间切换以进行读取和引用的主要目的是防止数据结构内出现过长的循环。
  • 当share_ptr在资源分配和分析期间承担管理资源的全部责任时,weak_ptr失去所有控制并被擦除。
  • weak_ptr永远不允许直接访问元素;相反,它使用拥有完整代码的shared_ptr对象来调用成员函数Lock来访问需要使用该资源的代码。
  • 一旦调用Lock或weak_ptr进行资源分配或控制任何bLock,就会生成一个空的weak_ptr对象。
  • 一旦Lock或weak_ptr被大多数shared_ptr对象共同引用或持有,一个完整的循环就完成或结束了。
  • 它不是仅仅使用weak_ptr (它是任何指针概念中指针完整工作格式的一个组成部分),而是在share_ptr的帮助下显着地利用所有资源。
  • shared_ptr利用weak_ptr获取锁的行为和weak_ptr的指向来使weak_ptr释放并释放末端资源。
  • 一旦上述所有资源被释放,列表及其相关节点也将被轻松删除和区分,从而创建优化的分析和格式大小调整方法。
  • 这个完整的周期由许多检查和方法组成,包括expired()方法,它用于确定所有权是否已过期。
  • 通过使用Lock(),您可以对某个资源获取单独的、独占的锁定,从而防止其他资源尝试以该资源为目标并在尝试这样做时导致冲突。
  • 之前使用owner()检查weak_ptr指向,如果指向正确则返回true。
  • 在整个周期内,使用Reset()释放所拥有的资源。
  • 当两个weak_ptr作用于对象时,使用swap ()技术。
  • 使用use_count()计算和跟踪shared_ptr对象的数量
  • 交换最初拥有的资源的技术是operator=。

C++中weak_ptr的例子:
以下是C++ 中的weak_ptr的一些示例:

include <iostream>  
include <memory>  
  
int main() {  
std::shared_ptr<int>sharedPtr = std::make_shared<int>(42);  
  
std::weak_ptr<int>weakPtr = sharedPtr;  
  
    if (auto LockedPtr = weakPtr.Lock()) {  
        // Use the weak pointer's shared object  
std::cout<< "Weak pointer value: " << *LockedPtr<< std::endl;  
    } else {  
std::cout<< "Weak pointer is expired" << std::endl;  
    }  
  
sharedPtr.reset(); // The shared pointer is reset, object may be deleted  
  
    if (auto LockedPtr = weakPtr.Lock()) {  
std::cout<< "Weak pointer value after reset: " << *LockedPtr<< std::endl;  
    } else {  
std::cout<< "Weak pointer is expired after reset" << std::endl;  
    }  
  
    return 0;  
}  

输出:
Weak pointer value: 42
Weak pointer is expired after reset

解释:

在本例中,共享指针 shared_Ptr 指向一个值为 42 的 int。之后,一个 sharedPtr 和一个 std::weak_ptrweakPtr 被创建。如果原始对象已被删除,Lock() 函数将返回一个空的共享指针,用于从弱指针中检索共享指针。

当程序使用弱指针访问共享对象时,会首先打印共享对象的值。然后,重置共享指针,模拟初始共享指针不再控制对象的情况。重置共享指针后,程序再次尝试使用弱指针访问对象。

示例 - 2:

include <memory>  
include <iostream>  
  
int main() {  
   // 创建一个指向值为 14 的 int 的共享指针;
std::shared_ptr<int>sharedPtr(new int(14));  
  
创建一个弱指针,与共享指针共享所有权;
std::weak_ptr<int>weakPtr(sharedPtr);  
  
    // 使用弱指针的 Lock() 函数访问对象  
    // 共享对象仍然存活,因此这将成功  ;
std::cout<< "Acquired weak_ptr through Lock(): " << *weakPtr.Lock() << std::endl;  
  
    // 检查弱指针是否过期  
    // 由于共享对象仍然有效,因此将输出 "false";
std::cout<< "Weak pointer expired: " << std::boolalpha<<weakPtr.expired() << std::endl;  
  
  重置弱指针;
weakPtr.reset();  
  
    // 检查弱指针在重置后是否过期  
    // 由于我们重置了弱指针,它不再与任何对象相关联  
    // 这将输出 "true"  ;
std::cout<< "Weak pointer expired after reset: " << std::boolalpha<<weakPtr.expired() << std::endl;  
  
    return 0;  
}  

输出:
Acquired weak_ptr through Lock(): 14
Weak pointer expired: false
Weak pointer expired after reset: true

案例3:

include <memory>  
include <iostream>  
  
int main() {  
   // 创建一个指向值为 8 的 int 的共享指针
std::shared_ptr<int> sharedPtr1(new int(8));  
  
     // 创建与共享指针共享所有权的弱指针
std::weak_ptr<int>weakPtr(sharedPtr1);  
  
std::cout<< "Count of sharedPtr1: " << sharedPtr1.use_count() << std::endl;  
std::cout<< "Count of weakPtr: " <<weakPtr.use_count() << std::endl;  
  
    // 创建另一个共享指针,与 sharedPtr1 共享所有权;
std::shared_ptr<int> sharedPtr2(sharedPtr1);  
  
std::cout<< "Count of sharedPtr1 after sharedPtr2 creation: " << sharedPtr1.use_count() << std::endl;  
std::cout<< "Count of weakPtr after sharedPtr2 creation: " <<weakPtr.use_count() << std::endl;  
  
    return 0;  
}  

输出:
Count of sharedPtr1: 1
Count of weakPtr: 1
Count of sharedPtr1 after sharedPtr2 creation: 2
Count of weakPtr after sharedPtr2 creation: 2

案例4:

include <memory>  
include <iostream>  
int main()  
{  
std::shared_ptr<int> shrd_ptr_1(new int(8));  
std::shared_ptr<int> shrd_ptr_2(new int(10));  
std::cout<< "*shrd_ptr_1 == " << *shrd_ptr_1 << std::endl;  
shrd_ptr_1.swap(shrd_ptr_2);  
std::cout<< "*shrd_ptr_1 == " << *shrd_ptr_1 << std::endl;  
swap(shrd_ptr_1, shrd_ptr_2);  
std::cout<< "*shrd_ptr_1 == " << *shrd_ptr_1 << std::endl;  
std::cout<< std::endl;  
std::weak_ptr<int> wk_ptr_1(shrd_ptr_1);  
std::weak_ptr<int> wk_ptr_2(shrd_ptr_2);  
std::cout<< "*wk_ptr_1 == " << *wk_ptr_1.Lock() << std::endl;  
wk_ptr_1.swap(wk_ptr_2);  
std::cout<< "*wk_ptr_2 == " << *wk_ptr_2.Lock() << std::endl;  
swap(wk_ptr_1, wk_ptr_2);  
std::cout<< "*wk_ptr_1 == " << *wk_ptr_1.Lock() << std::endl;  
return (0);  
}  

输出:
*shrd_ptr_1 == 8
*shrd_ptr_1 == 10
*shrd_ptr_1 == 8

*wk_ptr_1 == 8
*wk_ptr_2 == 10
*wk_ptr_1 == 8

该程序展示了如何利用 swap() 方法在需要获取所需资源时交换 weak_ptr,输出结果如图所示。

  • 在 shared_ptr 实例中,程序开始时创建了指向整数 8 和 10 的 shrd_ptr_1 和 shrd_ptr_2。
  • 然后,打印出 shrd_ptr_1 的值(即 8)。
  • 接下来,程序会使用成员函数 swap 和标准库中的 swap 函数交换 shrd_ptr_1 和 shrd_ptr_2 的内容。
  • 结果,shrd_ptr_1 的值从 8 变为 10,然后再变回来。

作为 shared_ptr 实例的一部分,程序创建了两个 weak_ptr 实例,即 wk_ptr_1 和 wk_ptr_2。wk_ptr_1 的值 8 被 t 打印出来。wk_ptr_1 和 wk_ptr_2 的值交换后,wk_ptr_1 现在包含数字 10。

程序结束时,再次切换 wk_ptr_1 和 wk_ptr_2,返回之前的所有权。然后打印 wk_ptr_1 的值,返回 8。

结论
C++ 的 weak_ptr 函数对于获取和访问列表节点的元素至关重要。此外,shared_ptr 和 weak_ptr 相互配合,为访问元素创建了一个优化的循环。一旦选择了 shared_ptr,一般就会认为这是一个永久性的操作。C++ 的 weak_ptr 函数在资源获取方面有许多优势。