<Effective Mordern C++>笔记:Item 5:Prefer auto to explicit type declarations.

来源:互联网 发布:淘宝客服网上人工服务 编辑:程序博客网 时间:2024/05/16 11:38

很多时候我们定义一个变量,都是直接的int x;根据编译器的不同,没有初始化的变量往往会有不同的未定义结果,进而产生各种各样的问题,在《Effective C++》中也有建议要养成初始化变量的习惯,使用auto可以省去判断各种变量类型的麻烦,但是auto是根据初始化值来判断的,所以变量必须初始化

除此之外,很多时候为了声明一个变量的类型,往往需要很长很啰嗦的前缀,比如在一个模板中,声明一个迭代器指向目标的类型:

template<typename It> void dwim(It b, It e) { while (b != e) {    typename std::iterator_traits<It>::value_type    currValue = *b;    }}

这样的代码让人看着就头疼…有了auto就可以直接 auto currValue = *b 了。

  • auto用于返回值的类型判断
auto derefUPLess =     [](const std::unique_ptr<Widget>& p1,     const std::unique_ptr<Widget>& p2)     { return *p1 < *p2; };

C++14中auto可以直接用于lambda表达式的参数中,那么我们甚至可以进一步的简化:

auto derefUPLess =     [](const auto& p1, const auto& p2)     { return *p1 < *p2; };    //简直不要太方便!!!

auto还有其他的优点。

例如在使用autostd::function时,两者的内存占用和运行效率就会有区别。
std::function是C++11中的一个可调用对象的模板,类似函数指针的作用,可以用来定义函数,lambda表达式和重载了()运算符的类。下面的例子:

bool(const std::unique_ptr<Widget>&,const std::unique_ptr<Widget>&)

这样的话上面的 derefUPLess这个函数就可以重写为不带auto的版本:

std::function<bool(const std::unique_ptr<Widget>&,const std::unique_ptr<Widget>&)> fuc;fuc= [](const std::unique_ptr<int>& p1,const std::unique_ptr<int>& p2) {    return *p1 < *p2;  };

虽然函数的目的都是一样的,但是内在还是有一些本质的区别,auto声明的是一个闭包类型,它所占内存即闭包类型需要的内存大小,而std::function是一个模板类,它声明的类型是模板的一个实例,但其分配的内存大小是固定的,当遇到内存大小不足时,会重新分配堆内存。结果就是:std::function对象基本会比auto对象占用更多的内存,且运行效率不及auto对象。

还有容器的size_type类型本质是unsigned,但是unsigned在32位和64位系统上的大小分别是32bits和64bits,如果用auto声明,不仅可以避免写出std::vector::size_type这样啰嗦的代码,还能避免不同机器下的大小不同问题。

再看别的特殊情况:

std::unordered_map<std::string, int> m;for (const std::pair<std::string, int>& p : m){… }

看起来没什么大问题,但是在unordered_map中,key是const类型的,我相信大多数人都会忽略这一点,平常的编码习惯也让我们直接这么写了,所以在哈希表中pair的类型应该是

for (const auto& p : m){… }

C++是一门强类型语言,有些人会担心auto将降低对变量类型的把握能力,这些其实可以借助Item4的办法在一定程度上解决,但在大多数情况下,自动推导的auto类型比一个容易出错的确定类型更能提高我们的效率,所以在大部分情况下,还是要多用auto的呀!!!

0 0
原创粉丝点击