Effective Modern C++读书笔记:auto(条款5-6)

条款5:优先选用auto,而非显示类型声明

1. 摆脱繁杂的类型声明

2.避免踩坑

1)使用auto与使用std::function声明闭包的对比
//使用std::function声明一个闭包
std::function<bool(const std::unique_ptr<Widget>&,
				   const std::unique_ptr<Widget>&)>
		 func = [](const std::unique_ptr<Widget>&p1,
	    		   const std::unique_ptr<Widget>&p2)
	    		   {return *p1 < *p2};
//使用auto声明一个闭包
auto func = [](const std::unique_ptr<Widget>&p1,
	    		   const std::unique_ptr<Widget>&p2)
	    		   {return *p1 < *p2};

使用auto除了声明上的方便,还有以下区别:使用auto声明的,存储该闭包的变量和该闭包是同一个类型,从而它要求的内存和闭包相同。而使用std::function声明的,存储闭包的变量只是std::function的一个实例,所以它具有固定的std::function类型的大小,而这个大小对闭包来说不一定够用,这种情况下,std::function的构造函数就会使用堆内存来使用该闭包。再有,编译器的实现细节一般都会限制内联,这种情况下会有函数调用的开销。
总结:std::function这种写法比auto来的 1.啰嗦 2.可能导致内存耗尽异常

2)类型窄化

考虑如下代码

std::vector<int> v;
...
unsigned size = v.size();

标准规定:v.size()返回应该是std::vector<int>::size_type,类型的不同可能会导致一些难以预料的错误。如在32位windows上,std::vector<int>::size_typeunsigned尺寸是一样的,而在64位windows上,unsigned是32位,而std::vector<int>::size_type是64位,这样可能会导致一些很难排查的异常。
而使用auto则会有效避免这个可能的错误

3)unordered_map

考虑如下代码:

std::unordered_map<std::string, int> m;
//some work to do 
for(const std::pair<std::string. int> &p:m){
//some work to do
}

想要发现上述代码的异常,就要记住std::unordered_map的键值部分是const,也就是m中存储的是std::pair<const std::string,int>,而不是std::pair<std::string, int>。上面的声明错误会使编译器想方设法将std::pair<const std::string,int>转化为std::pair<std::string, int>,它找到的方法是对m中的每个对象都做一次复制操作,把m中的元素复制到一个临时对象上,再把p绑定到这个临时对象上,在循环的每次迭代结束时,会再调用析构函数。除了调用构造函数和析构函数的开销之外,另一个可能引起灾难性后果的是对p取址,那么只是对临时对象取址,这可能会导致程序直接崩溃!

条款6:auto可能导致的不符合预期行为

auto返回隐形的代理类型导致不符合预期

考虑如下代码:

vector<bool> features();
auto ret = features()[5];

这里ret的类型并不是预期的bool类型,而是一个对用户隐形的std::vector<bool>::reference类型。这是因为vector<bool>operator []的返回值并不是bool,而是一个代理类型:std::vector<bool>::reference,而这可能会引起错误,严重甚至可能会产生空悬指针导致程序崩溃。
详细原因请参见Effective Modern C++ P47
再考虑如下代码:

vector<bool> features();
bool ret = features()[5];

上面的代码会使std::vector<bool>::reference隐示转化为bool对象,从而使后面的调用符和预期。
一个普遍的规律是:"隐形代理类"和auto无法和平共处

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值