c++中默认构造函数如何初始化变量

How variable is initialized by default constructor in c++

本文关键字:初始化 变量 构造函数 默认 c++      更新时间:2023-10-16

给定以下教程中的函数模板。

template<class T>
double GetAverage(T tArray[], int nElements)
{
    T tSum = T(); // tSum = 0
    for (int nIndex = 0; nIndex < nElements; ++nIndex)
    {
        tSum += tArray[nIndex];
    }
    // Whatever type of T is, convert to double
    return double(tSum) / nElements;
}

在线

T tSum = T(); // tSum = 0

他们说它将调用特定类型的默认构造函数(基于我们调用该函数的类型)。我怀疑这个调用是如何将值分配给tSum的,因为这将调用构造函数。但由于构造函数不返回任何内容,因此iSum是如何初始化为0表示int或0.0表示double的。

您正在阅读的教程对术语进行了一些严重的扭曲/简化。声明称

T tSum = T();

调用"默认构造函数"是不正确的。在一般情况下,类型T可以很容易地成为非类类型。非类类型没有任何构造函数,但是上面的初始化对它们也是有效的。

这种情况下的正确术语是值初始化。表达式T()生成由值初始化过程初始化的T类型的临时对象。值初始化根据其自身的特定规则进行,并且不一定涉及任何构造函数。对于非类类型以及某些类别的类类型,它以完全无构造函数的方式进行。

例如,表达式int()生成类型为int的值0,这就是值初始化对类型int(以及所有标量类型)的意义。当然,它不涉及任何"默认构造函数",因为类型int不可能有任何构造函数。

同样,表达式T()不是构造函数调用,因为该教程似乎错误地指出了这一点。表达式T()实际上是一个没有操作数的函数样式转换。如上所述,一个没有操作数的函数样式转换会生成一个值初始化的T类型的临时对象。它不依赖于构造函数"返回"任何内容。

临时值if T()表达式然后用作tSum对象的初始值设定项。此语法从T()调用tSum的复制初始化。

语句

T tSum = T();

表示"使用默认构造函数构造T类型的临时,然后复制/移动构造tSum",请参见C++n3376 ch8.5,p14。编译器允许(并且很可能会)将其优化为原位默认构造T tSum;请参见C++n3376 ch12.8,p31,复制省略,但复制/移动构造函数必须可用,请参见C++n3376 ch12.8 p32(考虑删除T的复制/移动构造器,它将无法编译)。

T()实际上创建了一个类型为T的临时对象,调用默认构造函数对其进行初始化。然后您就有了临时对象本身。

所以

T tSum = T();

将使用默认初始化的T临时实例初始化tSum

如果T是一个带有构造函数的类,那么所有这些似乎都不必要,但如果T是一个将tSum初始化为0的基本类型(如int)。由于在编写模板时,T的性质是未知的,因此代码会保护它。