用auto
声明的变量,它从初始化物来进行类型推导,所以它们必须初始化。
int x1; //有潜在的未初始化风险
auto x2; //编译错误!必须有初始化物
auto x3 = 0; //没问题
由于auto
使用了类型推导,所以它只能表示只有编译器掌握的类型。
auto derefUpLess =
[](const std::unique_ptr<Widget>& p1,
const std::unique_ptr<Widget>& p2)
{ return *p1 < *p2; }
在c++14中,lambda
表达式的形参中都可以使用auto
auto derefUpLess =
[](const auto& p1,
const auto& p2)
{ return *p1 < *p2; }
std::function
是C++11标准库中的一个模板,它把函数指针的思想加以推广。函数指针只能指向函数,而std::function
却可以指向任何可调用对象,即任何可以像函数一样实施调用之物。
创建一个一个函数指针就必须指定欲指向的函数的类型(即该指针指向的函数的签名),创建一个std::function
对象就必须指定欲指向的函数的类型。
举个例子,声明一个名为func
的std::function
对象,它可以指向任何能够以下述签名调用的对象。
bool(const std::unique_ptr<Widget>&, const std::unique_ptr<Widget>&);
//定义func
std::function<bool(const std::unique_ptr<Widget>&, const std::unique_ptr<Widget>&)> func;
因为lambda
可以产生可调用对象,std::function
对象中就可以存储闭包。这意味着,在C++11中,不用auto
就可以声明derefUpLess。
std::function<bool(const std::unique_ptr<Widget>&, const std::unique_ptr<Widget>&)>
derefUPLess = [](const auto& p1,
const auto& p2)
{ return *p1 < *p2; }
使用auto
和std::function
有所不同。使用auto
声明的,存储着一个闭包的变量和该闭包是同一类型,从而它要求的内存量也和该闭包一样。而使用std::function
声明的,存储着一个闭包的变量是std::function
的一个实例,所以不管给定的签名如何,他都占有固定尺寸的内存,而这个尺寸对于其存储的闭包而言并不一定够用。如果这样的话,std::function
的构造函数就会分配堆上的内存来存储该闭包。从结果上看,std::function
对象一般都会比使用auto
声明的变量使用更多的内存。
对于以下代码
std::vector<int> v;
unsigned sz = v.size();
标准规定,v.size()
的返回值类型为std::vector<int>::size_type
,但是std::vector<int>::size_type
是一个无符号整数。但是在32位windows上,unsigned
和std::vector<int>::size_type
的尺寸是一样的,但是在64位windows上,unsigned是32位,而std::vector<int>::size_type
是64位。这意味着,在32位windows上运行正常的代码在64位windows上可能会出现异常。而使用auto就可以保证你不会出现这样的问题。
auto sz = v.size(); //sz的类型是std::vector<int>::size_type
要点速记
auto
变量必须初始化,基本上对会导致兼容性和效率问题的类型不匹配现象免疫,还可以简化重构流程,通常也比显式指定类型要少打一些字。auto
类型的变量都有条款2和条款6中所描述的问题。