我有以下代码:
class A {
public:
A() { }
};
class B {
private:
const A &a;
public:
B() : a() { }
B(const A &ina) : a(ina) { }
};
在以下内容中编译结果:
ab.cpp:在构造函数'B :: B()'中:
ab.cpp:11:警告:'const A&的默认初始化B :: a',具有引用类型
为什么这会导致警告,我该如何解决?
答案 0 :(得分:12)
C ++语言中的引用可以被认为是其他对象的“替代名称”。名称总是指一个对象,没有该对象就不能存在,即引用不能“不引用任何东西”。这意味着引用必须在引用创建时立即绑定到目标对象,并且只要该引用存在,就保持绑定到该对象。该语言专门用于尽可能强制执行该规则。如果引用成员位于非聚合类类型中,则必须在构造函数初始化列表中显式初始化此类成员。
严格地说,要求默认初始化引用的程序格式不正确。在日常术语中,它应该是“错误”,而不是“警告”。所以,真正的“为什么”就是为什么你的编译器只发出一个警告(虽然正式的任何诊断信息足以报告格式错误的代码)。
答案 1 :(得分:4)
来自标准:
8.5.3参考文献[dcl.init.ref]
声明为T&的变量或T&&,即“对类型T的引用”(8.3.2),应由类型为T的对象或函数或可转换为T的对象初始化。
[...]
- 醇>
初始化程序只能在参数声明(8.3.5)中引用,在函数返回类型的声明中,在类定义(9.2)中的类成员声明中,并且显式使用extern说明符的地方。
B
的构造函数是错误的,因为它在内部调用了引用的默认构造函数,这是不可能的。
引用成员必须初始化构造函数的 member-initialization-list 。这就是你的默认构造函数不正确的原因。
答案 2 :(得分:2)
是UB。必须始终初始化引用。
答案 3 :(得分:1)
引用应始终引用变量。因此,B的第一个构造函数中的默认初始化没有意义。实际上,具有默认初始化的引用与具有根本未初始化的指针相同:两者都引用(或指向)内存中的随机位置。因此警告。