Effective Modern C++ 学习笔记(一)

《Effective Modern C++》学习记录(一)

类型推导

  1. 类型推导,主要是使用auto和decltype,更有可能只是前者(用的多)。Scott Meyers(作者)是提倡更多的使用auto,不使用具体的型别。并举例了使用auto的好处:
  • auto和decltype能使用的语境越来越多,不必再去写那些不言自明或者是完全冗余的型别。比如很长嵌套数据结构里面的迭代器。
  • 更高的适用性,如果在源码对一个型别改动,auto能自动适应,不用修改应用部分的代码。
  • 会强制要求变量初始化,不会有int i,而i忘了初始化的问题。
    (作者在后面还举了不少例子来说明好处)当然缺点是可能会导致写出来的代码比较难懂,编译器推导出来的类型,有时候不符合我们的想象。不过我认为可以辅助变量的命名,比如匈牙利命名等规范命名可以有效降低负面影响。之前有人说模版类型推导是否会影响程序的性能,并不会,内联编译,只是编译时使用,可能会导致代码体积膨胀,性能并不会受到影响。
  1. 函数模版类型的推导过程分两步:
	template<typename T>
	void f(const T& param);      // ParamType是const T&

	int x = 27;
	const int& rx = x;
	f(rx);  // 这里的T是const int不是const int&,param的类型是const int&
	f(x);  //  这里的T是int,param是int&

上面的这段代码,T和param是分开来推导的,在形参传入的时候,T的类型是忽略引用性的,也就是说对参数是T&传入const是安全的,不会发生改变。这一点在param处为按值类传递时,会进一步忽略param处的const或volatile。
3. 万能引用
也就是如下这种情况

	template<typename T>
	void f(T&& param);

	int x = 27;
	f(x);   // x是左值,那么T为int&,param为int&
	f(27);  // 27是右值,那么T为int,param为int&&

parm在这里是一个万能引用,很像右值引用,我简单理解就是能处理传入的实参为左值或右值的万能引用。当传入的是右值时,行为等同T&,当传入的为左值时,会有特殊处理。

auto使用

  1. auto的类型推导,除了个别情况,等同于上面的模版推导,两者之间存在双向的算法变换(我不会),或者说概念性等价。这里的auto相当于取代了模版中的ParamType,但是如果每次用auto的时候带入模版去思考一下,我感觉就很麻烦。
    以下的例子很能说明关系:
	auto x = 27;
	const auto cx = x;
	const auto& rx = x;

	auto&& uref1 = x;     // x是左值,int;那么按照T&处理,uref1是int&
	auto&& uref2 = cx;  // cx也是左值,const int;那么uref2是const int&
	auto&& uref3 = 27; // 27是右值,所以这里的uref3是一个万能引用,是int&&

不要以为带了&&就是万能引用,要看实际的赋值,实参部分是右值还是左值。
2. auto类型推导的一个例外跟初始化列表std::initializer_list有关。

	// 有以下四种初始化方式
	auto x1 = 27;
	auto x1(27);
	auto x1 = {27};
	auto x1{27};

其中,后两者的类型属于std::initializer_list,有类型收窄,也就是说auto x5 = {1,2,3.0};是通不过编译的,因为这会导致进行两次模版推导。这就很遗憾了,因为这会导致如果想用{}来统一C++中的初始化变量,会出现这个问题,导致有瑕疵。但是我还是认为这一点,记住就行,还是勉强可以认为{}统一了初始化。
而且如果直接传这个类型,模版会报错。

	auto x = {1,2,3};
	template<typename T>
	void f(T param);  // 如果说是std::initializer_list<T> param就不会报错

	f({1,2,3}); // 这样是会报错的

其余细节

  1. 如果用的多,比较熟练,以上才能学习的融会贯通,不然前期就需要停下来慢慢分析。如下:
	const int theAnswer = 42;
	auto x = theAnswer; 
	auto y = &theAnswer;

x是int,y是const int*。这是因为auto相当于模版推导的第二阶段,而如果param只是值传递,会忽视const。而&theAnswer是一个常量的地址,属于右值,而这个地址不能修改,所以是const int*。

对象初始化

C++11引入了{}大括号初始化,从概念上统一了初始化。值得一提的是,这种初始化把可能看上去像函数的变量初始化给干掉了,C++里面的声明只要能够被解析到,就认为是声明。Button pBtn(xxx)就不会出现是变量声明还是调用的问题了。类似的还有Button btn(),这到底是初始化还是一个函数的声明。
所以在设计类的时候,可以考虑加一个参数为初始列的构造函数。但是auto和初始列一起使用还是会出现上面提到的问题。这个东西有点坑,初始列会强烈的请求使用调用,即使类型不匹配,能隐式强制转换的,也会进行隐式转换。让我想到了突然兴奋的患者.jpg。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Effective Modern C++是一本由Scott Meyers所著的C++编程指南,该书针对C++11和C++14进行了全面介绍和分析。它是《Effective C++》的续作,适用于现代C++编程。对于C++开发者来说,它是一本非常宝贵的参考书。 PDF网盘是指网络上的一种存储和分享文件的服务平台。用户可以将文件上传到该平台,并与他人共享。这种服务通常提供了可在线浏览和下载文件的功能。 "Effective Modern C++ PDF网盘"这个问题的含义可能是在寻找《Effective Modern C++》这本书的PDF版本,并将其存储在PDF网盘上以供下载和分享。 寻找《Effective Modern C++》的PDF版本可以在搜索引擎上进行查找。一般来说,用户可以在一些知名的在线书店或学术资源网站上找到免费或付费的PDF版本。找到合适的文件后,用户可以将其上传到选择的PDF网盘,如Google Drive、百度云、Dropbox等。 将《Effective Modern C++》上传到PDF网盘上的好处是可以将文件与他人共享,并提供在线浏览和下载的功能。这样其他人可以方便地获取这本书的电子版本,而不必寻找纸质书或购买电子书。此外,PDF文件的格式保留了原始书本的版面结构,可以在不同设备上方便地阅读和浏览。 总之,《Effective Modern C++》是C++开发者的一本重要书籍,而PDF网盘是一个方便存储和分享文件的网络服务平台。将这本书的PDF版本上传到PDF网盘上,可以方便他人获取并进行阅读和学习

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值