我有以下代码:
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' 的默认初始化,它具有引用类型
为什么这会导致警告,我该如何解决?
我有以下代码:
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' 的默认初始化,它具有引用类型
为什么这会导致警告,我该如何解决?
C++ 语言中的引用可以被认为是其他对象的“替代名称”。名称始终指代一个对象,没有该对象就不能存在,即引用不能“引用任何内容”。这意味着引用必须在创建引用时立即绑定到目标对象,并且只要该引用存在,就一直绑定到该对象。该语言专门设计用于尽可能地执行该规则。对于非聚合类类型中的引用成员,这些成员必须在构造函数初始化器列表中显式初始化。
严格来说,调用默认初始化引用的程序是格式错误的。在日常命名中,它应该是一个“错误”,而不是一个“警告”。所以,这里真正的“为什么”是为什么你的编译器只发出警告(尽管形式上任何诊断消息都足以报告格式错误的代码)。
从标准:
8.5.3 参考文献 [dcl.init.ref]
声明为 T& 或 T&& 的变量,即“对 T 类型的引用”(8.3.2),应由 T 类型的对象或函数或可转换为 T 的对象初始化。
[...]
初始化器只能在参数声明 (8.3.5)、函数返回类型声明、类定义中的类成员声明 (9.2) 以及显式指定 extern 说明符的情况下省略引用用过的。
的构造函数B
是错误的,因为它在内部调用了引用的默认构造函数,这是不可能的。
必须在构造函数的成员初始化列表中初始化引用成员。这就是为什么您的默认构造函数格式错误的原因。
是UB。必须始终初始化引用。
引用应始终引用变量。因此,B 的第一个构造函数中的默认初始化没有意义。实际上,具有默认初始化的引用与具有根本未初始化的指针相同:两者都引用(或指向)内存中的随机位置。因此发出警告。