intrusive_ptr 使用基类进行引用计数并包含循环地狱

发布于 2024-12-23 12:03:24 字数 524 浏览 3 评论 0原文

我使用 boost::intrusive_ptr 作为我的引用计数智能指针。我正在使用这样的东西:

http://www.codeproject.com/KB/stl/boostsmartptr.aspx#intrusive_ptr%20-%20lightweight%20shared%20pointer

这似乎是个好主意,因为它简化了声明一个新的引用计数类,只是从它继承。问题来自于前向声明。有很多地方我想使用指向类定义中尚未声明的类型的指针,但这是不可能的,因为处理引用计数的 2 个方法需要知道该类型是否继承自 CRefCounted。

如果我尝试在 intrusive_ptr 声明之前包含依赖项,这是可以的,但是随后,我会得到很多循环包含。

你会如何处理这种情况?

I'm using boost::intrusive_ptr as my reference counted smart pointer. I'm using something like this:

http://www.codeproject.com/KB/stl/boostsmartptr.aspx#intrusive_ptr%20-%20lightweight%20shared%20pointer

This seems a good idea, because it simplifies the declaration of a new Reference counted class, just inheriting from it. The problem comes with forward declarations. There are a lot of places where I want to use a pointer to a type not yet decladed in a class definiton and it is not possible, because the 2 methods that handle ref count need to know if the type inherits from CRefCounted or not.

If I try to include the dependencies before the declaration of the intrusive_ptr it is ok, but then, I get a lot of cyclic includes.

How would you handle this scenario?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

青柠芒果 2024-12-30 12:03:24

我认为您可以使用 intrusive_ptr_add_refintrusive_ptr_release 的模板函数解决此问题,如下所示:

namespace boost {
  template<class T> void intrusive_ptr_add_ref(T* p) { ++(p->references) }
  template<class T>void intrusive_ptr_release(T* p) { 
    if (--(p->references) == 0) 
      delete p 
  }
};

您还需要调整 CRefCounted 中的友元声明,例如

template class<T> friend void ::boost::intrusive_ptr_add_ref(T*);
template class<T> friend void ::boost::intrusive_ptr_release(T*);

使用这些声明,您可以在前向声明的类上使用 intrusive_ptr

class A;
class B {
  ::boost::intrusive_ptr<A> _myPtr;
};
class A : public CRefCounted {
};

这种解决方案有一个缺点(理论上......),您定义了一对CRefCounted每个 子类的 add_ref/release 函数,但我认为编译器无论如何都会选择使用内联,所以这个可以忽略不计。

I think you can solve this using templates functions for intrusive_ptr_add_ref and intrusive_ptr_release as follows:

namespace boost {
  template<class T> void intrusive_ptr_add_ref(T* p) { ++(p->references) }
  template<class T>void intrusive_ptr_release(T* p) { 
    if (--(p->references) == 0) 
      delete p 
  }
};

You'll also need to adapt the friend declarations in CRefCounted like

template class<T> friend void ::boost::intrusive_ptr_add_ref(T*);
template class<T> friend void ::boost::intrusive_ptr_release(T*);

Using these declarations, you can use intrusive_ptr on forward-declared classes like

class A;
class B {
  ::boost::intrusive_ptr<A> _myPtr;
};
class A : public CRefCounted {
};

This solution has the drawback (theoretically...), that you define a pair of add_ref/release functions for every subclass of CRefCounted, but I think that the compiler will choose to use inlining anyway, so this can be neglected.

长发绾君心 2024-12-30 12:03:24

我经常使用类似的 RefCounted 基类,我开始想知道为什么我从来没有遇到过这个问题。这是因为我倾向于隐藏源文件中的实现细节。考虑类 B 的以下头文件:

//File: B.h
#include <boost/intrusive_ptr.hpp>

class A;

class B
{
public:
    B();
    ~B();
    boost::intrusive_ptr<A> foo();
    void foo2(const boost::intrusive_ptr<A> p);
    boost::intrusive_ptr<A> p;
};

它可以工作,因为即使它使用 intrusive_ptr,它也不需要实例化其构造函数或析构函数。因此它不需要知道关于类 A 的任何信息。

它需要了解 A 的地方是在源文件中。 (以及在调用 foo/foo2 的地方)。 B的构造函数和析构函数隐式调用intrusive_ptr< A> 的构造函数/析构函数,因此 A 的定义必须可用。

//File: B.cpp
#include "B.h"
#include "A.h" //Include header where A is defined.

B::B() { }
B::~B() { }

//Other member functions...

我不知道这对你的情况是否有帮助,但这是值得考虑的事情。 :)

I've been using a similar RefCounted base class a lot and I started wondering why do I never have this problem. And it's because I tend to hide implementation details in source files. Consider the following header file of class B:

//File: B.h
#include <boost/intrusive_ptr.hpp>

class A;

class B
{
public:
    B();
    ~B();
    boost::intrusive_ptr<A> foo();
    void foo2(const boost::intrusive_ptr<A> p);
    boost::intrusive_ptr<A> p;
};

It works, because even though it is using intrusive_ptr, it doesn't need to instantiate its constructor or destructor. Therefore it doesn't need to know anything about the class A.

The place where it needs to know about A is in the source file. (And also in places where foo/foo2 are called). B's constructor and destructor implicitly call intrusive_ptr< A>'s constructor/destructor, so A's definition must be available.

//File: B.cpp
#include "B.h"
#include "A.h" //Include header where A is defined.

B::B() { }
B::~B() { }

//Other member functions...

I don't know if this helps in your case, but it's something to think about. :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文