5

有没有办法在不使用指针的情况下定义循环引用?

我需要这样的东西:

struct A;
struct B {
    A a;
};

struct A {
    B b;
};

谢谢!

4

5 回答 5

15

您可以改用引用

struct A;
struct B {
  A& a;
};

struct A {
  B b;
};

但是不,如果没有某种程度的间接,就不可能创建循环引用。您的示例所做的甚至不是创建循环引用,而是尝试创建递归定义。结果将是一个无限大小的结构,因此是不合法的。

于 2009-08-25T16:03:39.253 回答
15

不,没有。这样的结构将有无限的大小。

您可以使用智能指针(shared_ptrweak_ptr)来避免直接的指针操作,但仅此而已。

于 2009-08-25T16:04:12.247 回答
7

这怎么能行?如果我没记错的话,引用的地址值一旦设置就不能修改,所以不能定义循环引用。

它可以像下面这样工作(与 Jared 的示例以及定义的构造函数相同):

struct A;

struct B {
  A& m_a;
  B(A& a) : m_a(a) {}
};

struct A {
  B m_b;
  //construct B m_b member using a reference to self
  A() : m_b(*this) {}
  //construct B m_b member using a reference to other
  A(A& other) : m_b(other) {}
};
于 2009-08-25T16:16:00.680 回答
1

在 C++ 中,T o表示“类型的对象T,而不是对某些对象的引用T(例如,在 C# 和 Java 中使用引用类型)。使用您问题中的代码,类型A将具有类型的子对象B(命名b),并且那B又会有一个类型的子对象A(名为a)。现在,这a又会有另一个A内部(再次称为a),然后有另一个B,它...

不,这行不通。

您可能想要的是 anA 引用a B,而后者又引用了 that A。这可以使用指针来完成:

struct A;
struct B {
    A* a;
    B(A*);
};

struct A {
    B* b;
    A(B* b_) : b(b_)  { if(b) b.a = this; }
};

B::B(A* a_) : : a(a_) { if(a) a.b = this; }

我不认为它可以使用引用来完成。

于 2009-08-25T17:35:47.913 回答
0

ChrisW 的解决方案可以概括如下:

template <class defaultState> struct Context;

struct State1 {
    Context<State1>& mContext;
    State1(Context<State1> & ref) : mContext(ref) {}
};

template <class TDefaultState>
struct Context {
    TDefaultState mState;
    Context() : mState(*this) {}
};

这现在允许你做

Context<State1> demo;

此外,State 也可以有一些模板帮助代码

template <class State>
struct TState {
    typedef Context<State> TContext;
    typedef TState<State> TBase;
    Context<State> & mContext;
    TState(Context<State> &ref) : mContext(ref) {}
};

struct State2 : TState<State2> {
    State2(TContext & ref) : TBase(ref) {}
};
struct State3 : TState<State3> {
    State3(TContext & ref) : TBase(ref) {}
};

现在允许您执行以下任何操作

Context<State2> demo2;
Context<State3> demo3;
于 2014-08-04T21:16:44.903 回答