typename关键字
当提到typename关键字时,首先想到的便是和class关键字一样,定义模板时引入一个模板参数,但除此之外,typename关键字还拥有另外一个功能——消除歧义:指明模板内部的一个标识符代表的一种类型,而不是一个静态成员,例如:typename T::SubType * ptr表示定义一个类型为T::SubType的指针变量,而不是T类型的静态成员变量和ptr相乘。先来看一个例子:
template <typename T>
long long Sum(const T &cont)
{
long long sum = 0;
T::const_iterator iter;
for (iter = cont.begin(); iter != cont.end(); ++iter)
sum += *iter;
return sum;
}
上面这段代码看似合情合理,然而却编译失败了,错误如下:
missing 'typename' prior to dependent type name 'T::const_iterator'
错误的意思是“嵌套类型'T::const_iterator'缺少typename关键字”。为什么必需要使用typename关键字?这与模板的编译机制有关。在模板实例化之前,编译器首先要对模板进行语法解析,但此时模板没有实例化,编译器无法确定T指向的具体类型,也就无法确认T::const_iterator到底是一个嵌套类型,还是一个静态成员变量,因此也就产生了歧义。将“T::const_iterator iter;”改为“typename T::const_iterator iter;”,告诉编译器T::const_iterator是一个嵌套类型,歧义就消除了。
即使模板嵌套类型用于返回值类型,也需要使用typename消除歧义。但这种情况下,编译器给出的是警告,而非错误。如下面的代码,编译器给出的就是警告“missing 'typename' prior to dependent type name T::size_type; implicit 'typename' is a C++20 extension [-Wc++20-extensions]”
template <typename T>
T::size_type GetContainerSize(const T &container)
{
return container.size();
}
零初始化
对于内置类型,比如 int,double 以及指针类型,由于它们没有默认构造函数,因此它们不 会被默认初始化成一个有意义的值。对于这些类型,只能通过显示的方式完成初始化,例如:
char *s = nullptr;
int i = 0;
double d = 0.0;
bool b = false;
C++11之前尽管