为什么引用类型成员的默认初始化会导致编译器警告?

时间:2013-08-21 21:05:54

标签: c++ reference const compiler-warnings

我有以下代码:

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',具有引用类型

为什么这会导致警告,我该如何解决?

4 个答案:

答案 0 :(得分:12)

C ++语言中的引用可以被认为是其他对象的“替代名称”。名称总是指一个对象,没有该对象就不能存在,即引用不能“不引用任何东西”。这意味着引用必须在引用创建时立即绑定到目标对象,并且只要该引用存在,就保持绑定到该对象。该语言专门用于尽可能强制执行该规则。如果引用成员位于非聚合类类型中,则必须在构造函数初始化列表中显式初始化此类成员。

严格地说,要求默认初始化引用的程序格式不正确。在日常术语中,它应该是“错误”,而不是“警告”。所以,真正的“为什么”就是为什么你的编译器只发出一个警告(虽然正式的任何诊断信息足以报告格式错误的代码)。

答案 1 :(得分:4)

来自标准:

  

8.5.3参考文献[dcl.init.ref]

     
      
  1. 声明为T&的变量或T&&,即“对类型T的引用”(8.3.2),应由类型为T的对象或函数或可转换为T的对象初始化。

  2.   
  3. [...]

  4.   
  5. 初始化程序只能在参数声明(8.3.5)中引用,在函数返回类型的声明中,在类定义(9.2)中的类成员声明中,并且显式使用extern说明符的地方。

  6.   

B的构造函数是错误的,因为它在内部调用了引用的默认构造函数,这是不可能的。

引用成员必须初始化构造函数的 member-initialization-list 。这就是你的默认构造函数不正确的原因。

答案 2 :(得分:2)

是UB。必须始终初始化引用。

答案 3 :(得分:1)

引用应始终引用变量。因此,B的第一个构造函数中的默认初始化没有意义。实际上,具有默认初始化的引用与具有根本未初始化的指针相同:两者都引用(或指向)内存中的随机位置。因此警告。