shared_ptr和weak_ptr之间的转换

20

我正在尝试使用 std::shared_ptrstd::weak_ptr 来操纵对象。场景如下:

我有一个类 channel 的对象,它派生自一个抽象类 abstract::channel(带有纯虚函数)。我有一个容器 channelContainer (std::vector),其中包含指向 channel 对象的共享指针 (std::shared_ptr)。

现在,我有一个 deque (std::deque),其中包含对于 channelContainer 中每个对象的弱指针 (std::weak_ptr)。让我们把这个 deque 命名为 freeChannelQueue

假设:

std::vector<std::shared_ptr<abstract::channel> > channelContainer;
std::deque<std::weak_ptr<abstract::channel > > freeChannelQueue;

//Assuming that both the containers are filled appropriately How do I go about implementeing the below functions?

abstract::channel& get_free_channel() {
  //This should return a free channel object from 'freeChannelQueue' and pop the queue.
}

bool release_channel(abstract::channel& ch) {
 //This should convert 'ch' to a std::weak_ptr (or std::shared_ptr) and push it to   'freeChannelQueue'
}

我特别关注“如何将引用转换为弱指针?”


据我所知,您无法直接从对象或对象引用初始化/构造 weak_ptr,因为它所引用的对象必须由 shared_ptr 拥有。因此,您需要一个 shared_ptrweak_ptr 来进行构造。 - Piotr99
3个回答

12

您无法将指向对象的引用转换为弱引用

您可以使用赋值符号=从共享指针创建一个弱指针,例如:

std::shared_ptr<abstract::channel> get_free_channel();

那么

bool release_channel(std::shared_ptr<abstract::channel> ch)
{
    std::weak_ptr<abstract::channel> weak_ch = ch;
    //...
}

注意生命周期 - shared_ptr会在指向它们的弱指针之前被销毁吗?


1

这是你的设计吗?按照现在的方式,存在一些严重的通道生命周期问题。例如 - 如果代码调用 get_free_channel(),则你的声明会向他们返回一个对象的引用,但他们无法保证其生命周期包含他们的使用。这可能取决于你从哪个客户端代码中调用该函数,但你可能想返回一个 shared_ptr,如下所示:

std::shared_ptr<abstract::channel> get_free_channel()
{
    // return free channel from 'freeChannelQueue' and pop the queue

    // take a scoped lock on the free queue if necessary

    while (!freeChannelQueue.empty())
    {
         auto p_channel = freeChannelQueue.back();
         freeChannelQueue.pop_back();
         std::shared_ptr<abstract::channel> p = p_channel.lock();
         if (p) return p;
    }

    // freeChannelQueue empty... throw or return nullptr etc..
}

关于“发布”...
bool release_channel(abstract::channel& ch) {
 //This should convert 'ch' to a std::weak_ptr (or std::shared_ptr) and push it to   'freeChannelQueue'
}

作为现有的情况,只有在搜索channelContainer以找到对象并从中获取弱指针或共享指针时才可能实现。再次强调 - 您应该更改原型,使其直接接收shared_ptrweak_ptr,锁定空闲队列,然后将智能指针推入其中...总的来说,在不了解您的通道生命周期如何管理以及各个线程如何尝试使用对象和队列的情况下,很难给出有用的建议。我希望上面的内容能够有所帮助,即使只是提出一个更精确的问题。

感谢您的答复,目前我已经得到了解决我的问题的答案。对于设计仍然不确定,如果我发现当前的设计不适合我的需求,我会更新问题! - user2559933
如果您将std::enable_shared_from_this作为基类,那么您可以将原始指针或引用转换为shared_ptr;您还可以为抽象类添加一个成员函数,该函数返回指向自身的shared_ptr。 - Dennis

0
我理解你的问题是这样的:你有一个容器来存储所有的通道对象,还有一个第二个容器来维护应用程序可以使用哪些通道的顺序。然后,你想要一个接口来为客户端返回下一个可用的通道的引用,当客户端完成后释放通道回到容器中。
为了获取通道的引用,你可以使用lock从weak_ptr创建shared_ptr,然后对其进行解引用(只是不要删除底层对象!)。但是,我没有看到任何合理的方法来反过来做,你需要在通道容器中搜索匹配的对象,并再次从匹配的shared_ptr创建一个weak指针。
我建议完全不使用weak_ptr和引用,而是坚持使用shared_ptr。由于你使用双端队列来维护可用通道,因此你可以在那里保留可用的shared_ptr。如果你确信客户端在完成后总是会释放通道,你可能不需要一个包含所有对象的容器,只需要deque来存储可用通道即可 - 这取决于你的整体设计。
正如其他人所说,你需要考虑你的通道对象的生命周期以及客户端如何使用它们。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接