Class A
{
A(B& b) : mb(b)
{
// I will not access anything from B here
}
B& mb;
};
Class B
{
B(): a(*this)
{}
A a;
}
我可能遇到这种情况,包含的对象需要使用容器功能。在包含的对象中引用容器对象似乎是执行此操作的最佳方法。当然,我可以用一个指针做这个,这样我就可以有一个setter setB(B* b) {mb = b;}
我可以在我确定B初始化后稍后调用但是我更喜欢用引用来做这个,这意味着我需要在构造函数中初始化它,因此问题。
答案 0 :(得分:9)
由于你只是初始化对B的引用,这应该没问题 - 当B的构造函数运行时,内存位置已经设置好了。
请记住,您无法从A的构造函数中安全地调用B中的任何方法,因为B尚未完成构建。
答案 1 :(得分:1)
这取决于你在A构造函数中做了什么。
在构造函数返回之前,B对象尚未完全构造。此外,在输入B构造函数的主体之前,B对象中的对象可能无法完全构造。例如:
class B
{
A a;
std::string str;
public:
B() : a(*this)
{
}
};
在调用A::A
时,尚未构建str
。如果您尝试在str
中使用A::A
(直接或间接),则会有未定义的行为。
答案 2 :(得分:1)
标准的适当引用是:
§3.8[basic.life] / 6
类似地,在对象的生命周期开始之前但在对象将占用的存储之后,或者在对象的生命周期结束之后以及在重用或释放对象占用的存储之前,任何左值可以使用引用原始对象但仅限于有限的方式。这样的左值是指分配的存储(3.7.3.2),并且使用不依赖于其值的左值的属性是明确定义的。如果将左值到右值转换(4.1)应用于这样的左值,则程序具有未定义的行为;如果原始对象是或者是非POD类类型,则在以下情况下程序具有未定义的行为:
— the lvalue is used to access a non-static data member or call a non-static member function of the object, or — the lvalue is implicitly converted (4.10) to a reference to a base class type, or — the lvalue is used as the operand of a static_cast(5.2.9) (except when the conversion is ultimately to char& or unsigned char&), or — the lvalue is used as the operand of a dynamic_cast(5.2.7) or as the operand oftypeid.