简体   繁体   English

C ++:对象的参考计数器

[英]C++: reference counter for objects

I need a reference counter for an object not allocated on the heap. 我需要一个未分配在堆上的对象的引用计数器。

I need it to implement a RAII mechanism on objects that cannot be easily copied and destructed: 我需要它在无法轻易复制和销毁的对象上实现RAII机制:

class File
{
private:
    int fd;
public:
    File( const std::string &path ) ... // opening file
    destroy( );                         // actually closing file

    File( const File &f ) ...           // just copying the fd
    ~File( );                           // doing nothing
}

For a scenario like this a std::shared_ptr is usually used: the constructor and the destructor of the object whose pointer is shared are called only once. 对于这种情况,通常使用std::shared_ptr :共享指针的对象的构造函数和析构函数仅被调用一次。

In my case, however, I'd prefer avoiding allocating the object on the heap. 但是,就我而言,我宁愿避免在堆上分配对象。 I'd need a shared_object class that does a job similar to std::shared_ptr , so that my class' non-copy-constructor and destroy function (in the example above) are called only once. 我需要一个shared_object类,该类的工作类似于std::shared_ptr ,这样我类的non-copy-constructor和destroy函数(在上面的示例中)仅被调用一次。

Does anything like this exist? 像这样的东西存在吗?

If you want to have shared pointer behavior while allocating nothing in dynamic storage ("on the heap") you can look at various smart pointer implementation strategies . 如果您希望在不分配任何动态存储空间(“在堆上”)的同时具有共享指针行为,则可以查看各种智能指针实现策略 In Modern C++ Design , the author discusses many of these strategies in the "Smart Pointers" chapter, which is freely (and legally) available online . 在“ 现代C ++设计”中 ,作者在“智能指针”一章中讨论了许多这些策略,该章可免费(合法)在线获得

The technique you will be interested in is reference linking . 您将感兴趣的技术是参考链接 Using this technique, the smart pointer objects are linked together in a bi-directional doubly linked list instead of pointing to a dynamically allocated reference counter. 使用这种技术,智能指针对象在双向双向链接列表中链接在一起,而不是指向动态分配的参考计数器。


All that being said, using a std::shared_ptr , std::unique_ptr or their Boost variants will probably be much faster to write and easier to maintain. 话虽这么说,使用std::shared_ptrstd::unique_ptr或它们的Boost变体可能会更快地编写并且更易于维护。 If dynamic allocation and the reference count are ever a bottleneck (I doubt it will be, but then we can't generalize too hastily), you can always take time to use a custom reference linking version instead. 如果动态分配和引用计数曾经是瓶颈(我怀疑会成为瓶颈,但是我们不能太仓促地归纳),那么您总是可以花一些时间来使用自定义引用链接版本。

You could provide your own deleter to a std::shared_ptr that will call your custom destroy function instead of delete. 您可以向std :: shared_ptr提供自己的删除程序,该调用程序将调用自定义的destroy函数而不是delete函数。

class File
{
private:
    int fd;
public:
    static void destroyThis(File* f){f->destroy();}
    File( const std::string &path ) ... // opening file
    void destroy( );                         // actually closing file

    File( const File &f ) ...           // You probably don't need this anymore.
    ~File( );                           // doing nothing
};

File fileObj("path");
std::shared_ptr<File> pf(&fileObj,std::bind(&File::destroyThis,std::placeholders::_1));
std::shared_ptr<File> pf2(pf);

I believe the following architecture meets your requirements: 我相信以下架构可以满足您的要求:

// pseudo-code
class File
{
private:
    int fd;
    File* prev;
    File* next;
public:
    File(const std::string &path) :
        fd(open(path)),
        prev(0),
        next(0)
    {}

    void destroy()
    {
        close(fd);
    }

    File( const File &f )
         fd(f.fd),
         prev(&f),
         next(f.next)
    {
         if (next)
             next->prev = this;

         f.next = this;
    }


    ~File()
    {
         if (prev)
            prev->next = next;

         if (next)
            next->prev = prev;

         if ((!prev) && (!next))
            destroy();
    }
};

A doubly linked-list is maintained between duplicate File instances. 在重复的File实例之间维护一个双向链表。 The last member of the list, and hence the last duplicate calls destroy. 列表的最后一个成员,因此最后一个重复的调用也将销毁。 No heap allocation required. 不需要堆分配。

(Obviously this isn't thread safe. You can protect with a mutex, or you can use lock-free methods for maintaining the list.) (显然,这不是线程安全的。您可以使用互斥锁进行保护,也可以使用无锁方法来维护列表。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM