浏览标准草案(n3242)我在第9.2条(强调我的)中找到了这句话:
非静态(9.4)数据成员不得有不完整的类型。在 特别是,C类不应包含类的非静态成员 C,但可以包含指针或引用到类的对象 下进行。
从此我认为可以定义这样的类:
class A {
public:
A(A& a) : a_(a){
}
private:
A& a_;
};
然后在第8.3.2节中,我发现了以下内容:
应初始化引用以引用有效对象或 功能
问题1:是否允许定义此类型的对象,并将其名称作为参考:
A a(a);
或者这会触发未定义的行为吗?
问题2:如果是,标准的哪些部分允许从仍待构建的对象初始化引用?
问题3:如果不是,这是否意味着A类的定义形式良好但是没有触发UB就可以创建第一个对象?在这种情况下,这背后的理由是什么?
答案 0 :(得分:8)
“有效对象”未在标准中的任何位置定义,但它旨在表示具有适当大小和对齐的内存区域,该区域可包含指定类型的对象。它只是意味着排除对诸如解除引用的空指针,未对齐的内存区域等内容的引用。未初始化的对象是有效的。
有一个未解决的问题需要澄清措辞CWG 453。
答案 1 :(得分:5)
n3337 § 3.8 / 6
同样,在对象的生命周期开始之前但在之后 对象占用的存储空间已被分配,或之后 对象的生命周期已经结束,在存储之前就已经存在了 对象占用被重用或释放,任何引用的glvalue 可以使用原始对象,但仅限于有限的方式。对于一个对象 正在建设或破坏,见12.7。否则,这样的glvalue 指分配存储(3.7.4.2),并使用的属性 不依赖于其值的glvalue是明确定义的。该程序 在以下情况下具有未定义的行为:
- 左值到左值的转换(4.1)是 应用于这样的glvalue,
- glvalue用于访问a 非静态数据成员或调用非静态成员函数 对象,或
- glvalue被隐式转换(4.10)为引用 到基类类型,或
- glvalue用作a的操作数 static_cast(5.2.9),除非转换最终是cv 焦炭和放大器;或cv unsigned char&,或
- glvalue用作的操作数 dynamic_cast(5.2.7)或作为typeid的操作数。
所以,回答你的问题:
问题1:是否允许定义此类型传递的对象 它的名字作为参考?
是。仅使用地址似乎不会违反这一点(至少对于放在堆栈上的变量)。
A a(a);
或者会触发未定义的行为吗?
没有
问题2:如果是,标准的哪些部分允许 从仍待构造的对象初始化引用?
§ 3.8 / 6(上图)
剩下的唯一问题是这与
的对应关系应初始化引用以引用有效对象或 功能
问题在于术语有效对象。因为§ 8.3.2 / 4表示
未指明引用是否需要存储
似乎§ 8.3.2是有问题的,应该重新编写。该错误导致文档 C ++标准核心语言活动问题,修订版87 日期为2014年1月20日的change proposed:
应初始化引用以引用对象或函数。
将8.3.2 [dcl.ref]第4段改为:
如果直接绑定引用的左值也不指定 现有的适当类型的对象或功能(8.5.3 [dcl.init.ref]),也不是合适大小和对齐的内存区域 包含引用类型的对象(1.8 [intro.object],3.8 [basic.life],3.9 [basic.types]),行为未定义。
答案 2 :(得分:0)
从n1905,3.3.1.1
名称的声明点在完成后立即生效 声明者(第8条)和初始化者(如果有的话)之前,除了 如下所述。
[例如:
int x = 12;
{int x = x; }这里是第二个x 用自己的(不确定的)值初始化。
-end example]
我的重点(如果我错了,请纠正我):在你的例子中 -
A a(a);
相当于 -
A a = a; // Copy initialization
因此,根据标准a
初始化它自己的不确定值。该成员正在提及一个这样的不确定值。