【问题标题】:Is there such a thing as a shared reference count smart pointer?是否有共享引用计数智能指针之类的东西?
【发布时间】:2012-11-29 06:01:06
【问题描述】:

使用boost::shared_ptr 的程序员需要避免循环,以免造成资源泄漏。一般建议是在可能创建此类循环的情况下使用boost::weak_ptr。然而,这样做会造成意图上的差距,人们可能更喜欢使用shared_ptr,但并不是因为循环问题才这样做。

不过,在我看来,应该可以创建一种特殊的 shared_ptr,通过链接循环中所有指针的引用计数来避免循环问题。既然我能想到一种方法来做到这一点,我想知道这样的事情是否存在。

为了证明我没有疯,或者我可能是疯了,我提供了以下经过深思熟虑和丑陋的概念证明:

#define BOOST_NO_MEMBER_TEMPLATE_FRIENDS

#include <boost/shared_ptr.hpp>
#include <iostream>

template <typename T>
struct shared_count_ptr
{
    boost::shared_ptr<T> innerPtr;
    template <typename TT>
    void link( boost::shared_ptr<T> & sharedPtr, boost::shared_ptr<TT> & linked )
    {
        innerPtr    = sharedPtr;
        innerPtr.pn = linked.pn;
    }
};

struct Hand;
struct Arm
{
    Arm()  { std::cout << "Creating Arm\n";   }
    ~Arm() { std::cout << "Destroying Arm\n"; }

    shared_count_ptr<Hand> hand;
};

struct Hand
{
    Hand()  { std::cout << "Creating Hand\n";   }
    ~Hand() { std::cout << "Destroying Hand\n"; }

    shared_count_ptr<Arm> arm;
};

int main()
{
    boost::shared_ptr<Arm> savedArm;

    std::cout << "Scope 0 entered\n";
    {
        std::cout << "\tScope 1 entered\n" ;

        boost::shared_ptr<Arm> arm( new Arm );
        {
            std::cout << "\t\tScope 2 entered\n";
            boost::shared_ptr<Hand>  hand( new Hand );

            hand->arm.link( arm, arm->hand );
            arm->hand.innerPtr = hand;

            savedArm = arm;
        }
        std::cout << "\t\tScope 2 exited\n";
    }
    std::cout << "\tScope 1 exited\n";
    std::cout << "\tScope 0 about to exit\n";

    return 0;
}

一般概念是在想象中的shared_count_ptr 眼中,手臂和手实际上是同一个对象。

所以:

  • boost中是否已经存在这样的想法?
  • 如果不是,是不是因为这是一个糟糕的主意?(或者我只是想出了一些聪明的办法?)

【问题讨论】:

  • 我无法想象需要通过一些小改动来轻松避免这种需求。我认为主要问题是有时(或经常)您可能不希望同时创建指针,这可能会使它变得更加复杂。或者强迫程序员显式链接指针只是自找麻烦。请注意,您的 shared_count_ptr 类可能不应该有 shared_ptr 成员,因为它已经继承了它,除非我误解了您的设计。
  • 继承是从 is-a 遗留下来的,并且将转到 has-a。固定的。我敢肯定有更好的方法来实现这一点,而且不会那么难看。
  • 我猜如果你的算法使用链表而不是简单的共享 int 计数器,你可以检测循环。

标签: c++ boost smart-pointers raii reference-counting


【解决方案1】:

这是一个简单的测试。在 17 个顶点上创建一个完整的图,这样程序只指向顶点 0。开始随机删除边。你的想法行得通吗? (剧透:它没有)。

【讨论】:

  • 即没有匹配的unlink,也不可能写一个。
  • 也许不是我的稻草人示例,但我相信它会是一个经过深思熟虑的实施。
  • 欢迎您尝试提出一个。我不会屏住呼吸。
  • 你可能是对的。我无法花费大量时间进行更多调查。然而,我的个人用例处于静态关系中,因此删除链接关系并不重要。
  • 没有任何引用计数方案可以自行检测循环,至少没有程序员的一些输入。如果你愿意提供这样的意见,当然,这是可能的。使用运行时可选策略制作智能指针(在强类型和弱类型之间进行选择)。这或多或少等同于您拥有的,但界面更简单。
【解决方案2】:

我想你可以按照这些思路做点什么。但是,在这样的结构中,每个指针 A 都需要了解每个其他指针 B,以便可以从 A 访问 B,反之亦然。我不明白这怎么可能扩展到超过少量互连的指针。

似乎如果你想在没有程序员帮助的情况下支持循环引用,你或多或少需要一个成熟的垃圾收集器而不是一个简单的引用计数方案(我很想在这方面被证明是错误的)。

【讨论】:

  • 一般概念(我的示例可能无法很好地表示)是您应该能够将引用计数和指向的类型的概念分开。从概念上讲,它应该缩放以及 smart_pointers 到同一对象的任何扩散。循环检测当然需要全面的垃圾收集。我的建议是,如果作者一开始就知道循环,那么应该可以使用该知识来避免问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多