gpt4 book ai didi

c++ - 为什么共享指针不会在 main 结束时超出范围?

转载 作者:行者123 更新时间:2023-12-02 16:08:08 25 4
gpt4 key购买 nike

我特意在下面的代码中引入了循环依赖。

我的疑问是,因为当共享指针 w 超出范围时,ref 计数不为零,因此 Widget 对象不会被销毁。

但是在 main 的末尾,共享指针“w->mGadget->mWidget”不会超出范围吗,因为众所周知,在 main 的末尾一切都不复存在了?我对这里的范围有点困惑。我期望当 main 退出时所有实体范围都应该结束。我的理解中缺失的环节在哪里?

#include <memory>
#include <iostream>

struct Gadget;

struct Widget
{
std::shared_ptr<Gadget> mGadget;
};

struct Gadget
{
std::shared_ptr<Widget> mWidget;
};

int main()
{
auto w = std::make_shared<Widget>();
w->mGadget = std::make_shared<Gadget>();
w->mGadget->mWidget = w;
return 0;
}

最佳答案

您混淆了 shared_ptr 的生命周期s 与它们引用的对象的生命周期。

std::shared_ptr维护指向对象的指针,并将该指针与引用计数相关联。 shared_ptr在引用计数降为 0 之前不会销毁指向的对象。

  • auto w = std::make_shared<Widget>();
    这将创建一个新的 Widget对象,然后创建一个新的 shared_ptr指向它,并设置 shared_ptr的引用计数为 1。

  • w->mGadget = std::make_shared<Gadget>();
    这将创建一个新的 Gadget对象,然后创建一个新的 shared_ptr指向它,并设置 shared_ptr的引用计数为 1。

  • w->mGadget->mWidget = w;
    这分配 wGadget对象的 mWidget成员,递增 Widget 的引用计数指向 2 的指针。

现在,当main()退出,唯一超出范围的变量是 w ,因此这是唯一被破坏的变量,减少了 Widget 的引用计数指向 1 而不是 0 的指针。并且由于仍然有对该指针的事件引用,Widget对象没有被销毁。自从它的mGadget成员积极引用了 Gadget指针,Gadget对象也没有被销毁。

要解决这个问题,您需要更改 Gadget::mWidget加入 std::weak_ptr相反:

#include <memory>

struct Gadget;

struct Widget
{
std::shared_ptr<Gadget> mGadget;
};

struct Gadget
{
std::weak_ptr<Widget> mWidget; // <-- here
};

int main()
{
auto w = std::make_shared<Widget>();
w->mGadget = std::make_shared<Gadget>();
w->mGadget->mWidget = w;
return 0;
}

std::weak_ptr不会增加 std::shared_ptr的引用计数(至少直​​到 std::weak_ptr::lock() 被调用),所以 Widget指针的引用计数将是 1 而不是 2。所以当 w超出范围并被销毁,Widget 的引用计数指针下降到 0,破坏了 Widget对象,这将破坏它的 mGadget成员,这将减少 Gadget 的引用计数指向 0 的指针,破坏了 Gadget对象。

关于c++ - 为什么共享指针不会在 main 结束时超出范围?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68792322/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com