c++中默认构造函数如何初始化变量
How variable is initialized by default constructor in c++
给定以下教程中的函数模板。
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
的性质是未知的,因此代码会保护它。
- 初始值设定项列表是否只接受使用相同类型的值初始化变量?
- 在 C++ 中访问 lambda 捕获初始化变量
- 为什么C++不支持对未初始化变量进行智能分析?
- 使用 clang++ 和 g++ 在C++中初始化变量
- C++使用 lambda 初始化变量
- 如何在初始化列表中的构造函数之后初始化变量/对象?
- C++ - 输出与初始化变量不同?
- C++/Win32 构造函数不使用从对话框获取的字符串初始化变量
- 在C++中,为什么int可以使用new运算符初始化变量,而double不能
- 具有静态存储持续时间的常量初始化变量的初始化顺序
- C++ 中的初始化变量
- C++中未初始化变量的值
- 如何在需要提及需要循环声明的其他类的类中初始化变量?
- 我想知道在构造函数中初始化变量时的生命周期
- 读取恰好具有良好值的未初始化变量
- 如何在 getter 的父类中初始化变量的情况下访问子类中的变量
- 为什么在 c++ 中有多种初始化变量的方法
- 没有参数的默认构造函数是否总是初始化变量?
- 是否可以使用 lambda 初始化变量(删除复制 ctor 时)
- 使用构造函数跳闸UB的新放置后使用初始化变量