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

问题描述:

据我所知,要在类中初始化引用成员变量我必须使用初始化列表使用参数化构造函数来初始化成员变量。 另外我明白,没有必要的默认构造函数。引用成员变量初始化错误与默认的构造函数

问:

  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成员函数过的行为。引用和const成员变量的原因是否相同?

+0

你也可能想重新考虑拥有一个引用成员 - 这很少是一个好主意。 –

why defining a default constructor throws compilation error?

这不是您定义的默认构造函数,它的默认构造函数的定义不初始化i。您需要需要才能初始化所有引用的成员变量,而您的空白定义不会这样做。

这是你需要初始化引用变量一样的道理:

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

why would the compiler allow declaration of default constructor(without definition)

因为定义是问题,而不是申报。例如,移动病态的构造函数定义的类定义之外将产生同样的错误:

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) {} 
+0

嗯,问题更多:_当我已经提供了一种方式来初始化通过参数化构造函数的成员变量,那么为什么寻找默认构造函数?此外,在参数化构造函数的存在下,如果不允许定义默认构造函数,那么为什么还应该允许默认构造函数的声明呢? _ – anurag86

+0

@ anurag86 *“在参数化构造函数存在的情况下,如果不允许使用默认构造函数的定义”* - 允许使用默认构造函数**的定义**,您刚提供了一个不合格的定义,因为它没有' t初始化'我'。 **如果完全删除参数化的构造函数,将会遇到相同的错误。** – cdhowie

+0

明白了。谢谢。 – anurag86

编译器要求对所有引用进行初始化。如果你定义了一个默认的构造函数,那么编译器会抱怨,因为你没有初始化i。如果你声明了默认构造函数,那么你还没有定义它,所以编译器没有问题。考虑这个:

class SomeClass 
{ 
    SomeClass(); // Compiler is fine with this 
    ... 
}; 

int someInt; 
SomeClass::SomeClass(): i(someInt) {} // OK - i is initialized 

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

+0

如果是这样,为什么甚至会允许一个声明? – anurag86

+0

@ anurag86为什么不呢?您稍后可能想要派生'SomeClass'并使用调用基类的默认ctor的自定义初始化程序列表。 – George

+0

@ anurag86,因为编译器只关心定义。它不知道你是否将初始化引用时,它只是声明 – Kevin

首先是其失败的基准部件的所要求的初始化一个构造的实施方案:
SomeClass(){}

第二种是仅一个构造的声明。只要它没有得到执行,缺乏实施就不成问题。和,只要它不实现的(可能的)未初始化是没有问题的:
SomeClass();

注意,非参数化的构造能正确初始化的基准构件,例如引用全局变量或静态变量。这可能对任何事情都没有用处,但这是可能的。所以对于编译器来说,第二个版本不是直接的问题,并不一定表示其他地方的实际问题。