使用默认构造函数引用成员变量初始化错误



我知道要初始化类中的引用成员变量,我必须使用初始值设定项列表,使用参数化构造函数来初始化成员变量。 我也明白不需要默认构造函数。

问题:

  1. 但我不明白的是为什么定义默认构造函数会引发编译错误? 编译器是否不够聪明,无法在以下情况下考虑参数化构造函数而不是抛出错误?

  2. 如果上述问题有令人信服的答案,那么为什么编译器允许声明默认构造函数(没有定义(? 它在这里有什么区别?

class SomeClass
{
public:
//SomeClass(){} //THIS IS AN ISSUE
//SomeClass();  //THIS IS FINE THOUGH

SomeClass(int j):i(j){}
int& i;
};
int main()
{
SomeClass obj(2);
return 0;
}

我相信 const 成员函数的行为也是如此。引用和常量成员变量的原因是否相同?

为什么定义默认构造函数会引发编译错误?

不是你定义了默认构造函数,而是默认构造函数的定义没有初始化i。您需要初始化所有作为引用的成员变量,而空定义不会这样做。

这与初始化引用变量所需的原因相同:

void foo() {
int &i; // error: declaration of reference variable 'i' requires an initializer
}

为什么编译器允许声明默认构造函数(没有定义(

因为定义是问题,而不是声明。 例如,将格式错误的构造函数定义移到类定义之外将产生相同的错误:

class SomeClass
{
public:
SomeClass();
int &i;
};
SomeClass::SomeClass() {} // error: constructor for 'SomeClass' must explicitly initialize the reference member 'i'

这两个示例的唯一问题是您没有初始化i

请注意以下示例,这些示例将进行编译。 请注意,构造函数的声明不会更改,但定义会初始化i

int someGlobalInt;
class SomeClass
{
public:
SomeClass() : i(someGlobalInt) {}
int &i;
};

int someGlobalInt;
class SomeClass
{
public:
SomeClass();
int &i;
};
SomeClass::SomeClass() : i(someGlobalInt) {}

编译器要求初始化所有引用。如果您定义了一个不执行任何操作的默认构造函数,则编译器会抱怨,因为您没有初始化i。如果声明默认构造函数,则尚未定义它,因此编译器没有问题。考虑一下:

class SomeClass
{
SomeClass(); // Compiler is fine with this
...
};
int someInt;
SomeClass::SomeClass(): i(someInt) {} // OK - i is initialized

您稍后定义了构造函数并初始化了i

第一个是构造函数的实现,它未能达到引用成员所需的初始化:
SomeClass(){}

第二个只是构造函数的声明。只要不被执行,缺乏实现就不是问题。只要它没有实现,(可能(初始化失败就不是问题:
SomeClass();

请注意,非参数化构造函数可以正确初始化引用成员,例如对全局变量或静态变量的引用。这可能对任何事情都没有用,但这是可能的。因此,对于编译器来说,第二个版本不是直接的问题,也不一定表明其他地方存在实际问题。

最新更新