C++ 构造函数初始化列表中的循环依赖项

C++ 构造函数初始化列表中的循环依赖项,c++,constructor,initialization,circular-dependency,initialization-list,C++,Constructor,Initialization,Circular Dependency,Initialization List,以下定义是否明确 class A; class B; // define A, which takes B& in constructor // define B, which takes A& in constructor class C { A a; B b; public: C() : a(b), b(a) { /* stuff with a and b */ } } 完整示例见 只要A和B的构造函数不处理他们得到的引用,它是否安全/定义良好

以下定义是否明确

class A;
class B;

// define A, which takes B& in constructor
// define B, which takes A& in constructor

class C
{
    A a;
    B b;
public:
    C() : a(b), b(a) { /* stuff with a and b */ }
}
完整示例见


只要
A
B
的构造函数不处理他们得到的引用,它是否安全/定义良好

N4140[class.cdtor]/1内容如下:

对于具有非平凡构造函数的对象,引用该对象的任何非静态成员或基类 在构造函数开始执行之前,将导致未定义的行为。对于具有非平凡 析构函数,指析构函数完成后对象的任何非静态成员或基类 执行会导致未定义的行为

虽然这篇文章本身并不意味着行为在其他方面是明确定义的,但下面的例子表明它是正确的。以下是摘录:

struct B : public A { int j; Y y; }; // non-trivial
extern B bobj;
B* pb = &bobj; // OK

因此答案是:是的,如果您在
A

的构造函数中没有引用
b
的成员或基类,那么您案例中的行为是很好定义的。为什么要投否决票?让我知道如何改进这个问题。我认为编译器不允许您执行
a(b)
,因为当
a
被初始化时,
b
还没有初始化。@user3528438:当然可以,ideone示例编译并运行。但这是因为我很幸运,还是因为它在标准中定义得很好?有趣的是,对象似乎是“已分配但未初始化”的。这很直观。这就是未定义的行为,因为
m_a.m_值
是在
m_a
的构造函数运行之前访问的。谢谢你挖掘参考资料@Claudiu是的,它绝对是UB。你能把一个引用绑定到一个还没有被构造的对象上吗?指针和引用的语义之间存在差异。例如,
int*p=nullptr;int&r=*p被认为是UB,但
int*r=&*p
可以说不是UB(例如,C显式允许)。@dyp不幸的是,我找不到关于引用的显式引用,只是[class.cdtor]/3可能暗示,如果我们有东西要转换,它是通过定义良好的方法获得的。