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

时间:2013-12-11 07:29:08

标签: c++ templates

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

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。

3 个答案:

答案 0 :(得分:6)

您正在阅读的教程会产生一些严重的术语扭曲/简化。声明说

T tSum = T();

调用“默认构造函数”不正确。从一般情况来看,很明显,类型T很容易成为非类型。非类类型没有任何构造函数,但上面的初始化对它们也有效。

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

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

同样,表达式T()不是构造函数调用,因为该教程似乎错误地说明了。表达式T()实际上是一个没有操作数的函数式转换。如上所述,没有操作数的函数式转换产生了T类型的值初始化临时对象。它不依赖于构造函数“返回”任何东西。

如果T()表达式随后用作tSum对象的初始化程序,则为临时值。此语法从tSum调用T()的复制初始化。

答案 1 :(得分:3)

声明

T tSum = T();

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

答案 2 :(得分:1)

T()实际上创建了一个T类型的临时对象,调用默认构造函数来初始化它。然后你就拥有了临时对象。

所以

T tSum = T();

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

如果T是带有构造函数的类,则所有这些似乎都是不必要的,但如果T是基本类型(例如int),则会将tSum初始化为0。因为当您编写模板时T的性质未知,所以代码可以安全地使用它。