当前位置:嗨网首页>书籍在线阅读

05-声明

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

18.1.3 声明

C++11提供了多种简化声明的功能,尤其在使用模板时。

1.auto

以前,关键字auto是一个存储类型说明符(见第9章),C++11将其用于实现自动类型推断(见第3章)。这要求进行显式初始化,让编译器能够将变量的类型设置为初始值的类型:

auto maton = 112; // maton is type int
auto pt = &maton; // pt is type int *
double fm(double, int);
auto pf = fm;      // pf is type double (*)(double,int)

关键字auto还可简化模板声明。例如,如果il是一个std::initializer_list对象,则可将下述代码:

for (std::initializer_list<double>::iterator p = il.begin();
                                             p !=il.end(); p++)

替换为如下代码:

for (auto p = il.begin(); p !=il.end(); p++)

2.decltype

关键字decltype将变量的类型声明为表达式指定的类型。下面的语句的含义是,让y的类型与x相同,其中x是一个表达式:

decltype(x) y;

下面是几个示例:

double x;
int n;
decltype(x*n) q; // q same type as x*n, i.e., double
decltype(&x) pd; // pd same as &x, i.e., double *

这在定义模板时特别有用,因为只有等到模板被实例化时才能确定类型:

template<typename T, typename U)
void ef(T t, U u)
{
    decltype(T*U) tu;
    ...
}

其中tu将为表达式TU的类型,这里假定定义了运算TU。例如,如果T为char,U为short,则tu将为int,这是由整型算术自动执行整型提升导致的。

decltype的工作原理比auto复杂,根据使用的表达式,指定的类型可以为引用和const。下面是几个示例:

int j = 3;
int &k = j
const int &n = j;
decltype(n) i1;      // i1 type const int &
decltype(j) i2;      // i2 type int
decltype((j)) i3;    // i3 type int &
decltype(k + 1) i4;  // i4 type int

有关导致上述结果的规则的详细信息,请参阅第8章。

3.返回类型后置

C++11新增了一种函数声明语法:在函数名和参数列表后面(而不是前面)指定返回类型:

double f1(double, int);         // traditional syntax
auto f2(double, int) -> double; // new syntax, return type is double

就常规函数的可读性而言,这种新语法好像是倒退,但让您能够使用decltype来指定模板函数的返回类型:

template<typename T, typename U)
auto eff(T t, U u) -> decltype(T*U)
{
    ...
}

这里解决的问题是,在编译器遇到eff的参数列表前,T和U还不在作用域内,因此必须在参数列表后使用decltype。这种新语法使得能够这样做。

4.模板别名:using =

对于冗长或复杂的标识符,如果能够创建其别名将很方便。以前,C++为此提供了typedef:

typedef std::vector<std::string>::iterator itType;

C++11提供了另一种创建别名的语法,这在第14章讨论过:

using itType = std::vector<std::string>::iterator;

差别在于,新语法也可用于模板部分具体化,但typedef不能:

template<typename T>
  using arr12 = std::array<T,12>; // template for multiple aliases

上述语句具体化模板array<T, int>(将参数int设置为12)。例如,对于下述声明:

std::array<double, 12> a1;
std::array<std::string, 12> a2;

可将它们替换为如下声明:

arr12<double> a1;
arr12(std::string> a2;

5.nullptr

空指针是不会指向有效数据的指针。以前,C++在源代码中使用0表示这种指针,但内部表示可能不同。这带来了一些问题,因为这使得0即可表示指针常量,又可表示整型常量。正如第12章讨论的,C++11新增了关键字nullptr,用于表示空指针;它是指针类型,不能转换为整型类型。为向后兼容,C++11仍允许使用0来表示空指针,因此表达式nullptr == 0为true,但使用nullptr而不是0提供了更高的类型安全。例如,可将0传递给接受int参数的函数,但如果您试图将nullptr传递给这样的函数,编译器将此视为错误。因此,出于清晰和安全考虑,请使用nullptr ——如果您的编译器支持它。