写了非常多关于C++11的博客.总是认为不踏实,非常多东西都是东拼西凑.市场上也非常少有C++11的优秀书籍,但幸运的是Meyers老爷子并没有闲赋.为我们带来了<effective modern c++>. 我们都要认清,一个人非常难超越自我,超越自我的巅峰之作.由于不同的时代.也会早就不同的伟大作品. 说上面这段话的意思就是,我们不能期待<effective modern c++>能达到<effective c++>给我们带来的惊喜,可是也是出自大师之手. Lear…
/*********************************************************** 关于书: 书是我从网上找到的effective Modern C++的样章,内容只到条款4就没有了, 所以现阶段我只能翻译到条款4,不过以后有机会我会继续翻译的. 如果读者找到了完整的版本,欢迎大家发给我.1021842556@qq.com effective Modern C++的样章的下载地址http://pan.baidu.com/s/1ntKBlpf 提取密码是upk…
北京时间2016年1月9日10:31:06.正式開始翻译.水平有限,各位看官若有觉得不妥之处,请批评指正. 之前已经有人翻译了前几个条目,有些借鉴出处:http://www.cnblogs.com/magicsoar/p/3966177.html?utm_source=tuicool&utm_medium=referral 如今就開始<Effective Modern C++>翻译之旅,第一个姿势--简单介绍 Introduction 假设您是一位专家级别的C++project师,和我…
本文记录了我读Effective Modern C++时自己的一些理解和心得. item1:模板类型推导 1)reference属性不能通过传值参数传入模板函数.这就意味着如果模板函数需要一个reference类型的参数,必须在模板声明中将其声明为reference,否则,即使使用一个reference类型的变量调用模板函数,类型推导的结果将不带reference属性. 2)constant和volatile属性也不能通过传值参数传入模板函数,但是可以通过reference参数传入这些属性. 3…
条款6:当auto推导出意外的类型时,使用显式的类型初始化语义 条款5解释了使用auto来声明变量比使用精确的类型声明多了了很多的技术优势,但有的时候,当你想要zag的时候,auto可能会推导出了zig.例如,我有一个函数,它以const Widget&作为参数,并且返回std::vector<bool>,每一个bool暗示了Widget是否提供了一个特殊的特性. std::vector<bool> features(const Widget& w); 进一步假设第…
条款3 了解decltype decltype是一个有趣的东西,给它一个变量名或是一个表达式,decltype会告诉你这个变量名或是这个表达式的类型,通常,告诉你的结果和你预测的是一样的,但是偶尔的结果也会让你挠头思考,开始找一些参考资料进行研究,或是在网上寻找答案. 我们从典型的例子开始,因为它的结果都是在我们预料之中的,和模板类型推导与auto类型推导相比(参见条款1和条款2),decltype几乎总是总是返回变量名或是表达式的类型而不会进行任何的修改 ; // decltype(i)是co…
条款2 明白auto类型推导 如果你已经读完了条款1中有关模板类型推导的内容,那么你几乎已经知道了所有关于auto类型推导的事情,因为除了一个古怪的例外,auto的类型推导规则和模板的类型推导规则是一样的,但是为什么会这样呢?模板的类型推导涉及了模板,函数和参数,但是auto的类型推导却没有涉及其中的任何一个. 这确实是对的,但这无关紧要,在auto类型推导和template之间存在一个直接的映射,可以逐字逐句的将一个转化为另外一个. 在条款1中,模板类型推导是以下面的模板形式进行举例讲解的:…
条款2: 理解auto自己主动类型推导 假设你已经读过条款1关于模板类型推导的内容,那么你差点儿已经知道了关于auto类型推导的所有. 至于为什么auto类型推导就是模板类型推导仅仅有一个地方感到好奇.那是什么呢?即模板类型推导包含了模板.函数和參数,而auto类型判断不用与这些打交道. 这当然是真的.可是没关系. 模板类型推导和auto自己主动类型推导是直接匹配的. 从字面上看,就是从一个算法转换到还有一个算法而已. 在条款1中.阐述模板类型推导採用的是常规的函数模板: template<ty…
第一章 类型推导 C++98有一套单一的类型推导的规则:用来推导函数模板,C++11轻微的修改了这些规则并且增加了两个,一个用于auto,一个用于decltype,接着C++14扩展了auto和decltype可以使用的语境,类型推导的普遍应用将程序员从必须拼写那些显然的,多余的类型的暴政中解放了出来,它使得C++开发的软件更有弹性,因为在某处改变一个类型会自动的通过类型推导传播到其他的地方. 然而,它可能使产生的代码更难观察,因为编译器推导出的类型可能不像我们想的那样显而易见. 想要在现代C+…
条款4:了解如何观察推导出的类型 那些想要知道编译器推导出的类型的人通常分为两种,第一种是实用主义者,他们的动力通常来自于软件产生的问题(例如他们还在调试解决中),他们利用编译器进行寻找,并相信这个能帮他们找到问题的源头(they’re looking for insights into compilation that can help them identify the source of the problem.).另一种是经验主义者,他们探索条款1-3所描述的推导规则,并且从大量的推导情…
    在概念上说,auto关键字和它看起来一样简单,但是事实上,它要更微妙一些的.使用auto会让你在声明变量时省略掉类型,同时也会防止了手动类型声明带来的正确性和性能上的困扰:虽然按照语言预先定义的规则,一些auto类型推导的结果,在程序员的视角来看却是难以接受的,在这种情况下,知道auto是如何推导答案便是非常重要的事情,因为在所有可选方法中,你可能会回归到手动的类型声明上(because falling back on manual type declarations is an alt…
条款4:了解怎样查看推导出的类型 那些想要了解编译器怎样推导出的类型的人通常分为两个阵营. 第一种阵营是实用主义者.他们的动力通常来自于编敲代码过程中(比如他们还在调试解决中),他们利用编译器进行寻找,并相信这个能帮他们找到问题的根源.另外一种是经验主义者.他们正在探索条款1-3所描写叙述的推导规则. 而且从大量的推导情景中确认他们预測的结果("对于这段代码,我觉得推导出的类型将会是-"),可是有时候.他们仅仅是想简单的回答假设这样,会怎么样呢之类的问题?他们可能想知道假设我用一个un…
裸指针有着诸多缺点:裸指针的声明中看不出它指向的是单个对象还是数组:裸指针的声明中也无法看出使用完它指向的对象后是否需要删除,也就是声明中看不出裸指针是否拥有其指向的对象:即使知道要析构裸指针指向的对象,也不可能知道如何析构才是恰当的:即使确知要使用delete来析构,也无法判定到底使用delete还是delete[]:使用裸指针也无法保证在程序多个代码路径上仅执行一次析构,不执行析构会造成内存泄漏,多次析构又会产生未定义行为:无法判断出裸指针是否是空悬指针. 智能指针的提出,就是用来解决裸指针…
07:在创建对象时注意区分()和{} 自C++11以来,指定初始化值的的方式包括使用小括号,等号,以及大括号: ); // initializer is in parentheses ; // initializer follows "=" }; // initializer is in braces }; // initializer uses "=" and braces C++将后两种使用大括号的两种方式视为相同的方式. C++11之前,单纯的直接初始化和复制…
C++的官方钦定版本,都是以ISO标准被接受的年份命名,分别是C++98,C++03,C++11,C++14,C++17,C++20等.C++11及其后续版本统称为Modern C++. C++11之前,仅有一套类型推导规则,也就是函数模板的推导.C++11之后,又增加了了auto和decltype的推导规则.模板推导规则是auto的基础. 首先需要介绍顶层const和底层const 的概念:指针本身是不是常量以及指针所指的对象是不是一个常量,这是两个相互独立的问题.顶层const(top-le…
Item 1: Understand template type deduction. Item 2: Understand auto type deduction. Item 3: Understand decltype. Item 4: Know how to view deduced types. Item 5: Prefer auto to explicit type declarations. Item 6: Use the explicitly typed initializer i…
条款7 辨别使用()与{}创建对象的差别 基础知识 目前已知有如下的初始化方式: ); ; }; }; // the same as above 在以“=”初始化的过程中没有调用赋值运算,如下例所示: Widget w1; // default ctor Widget w2 = w1; // copy ctor w1 = w2; // assignment, operator = 还可以用来初始化: class Widget { }; // fine ; // fine ); // error…
条款6 当推断意外类型时使用显式的类型初始化语句 基础知识 当使用std::vector<bool>的时候,类型推断会出现问题: std::vector<bool> features(const Widget& w); // OK ]; processWidget(w, highPriority); // ERROR auto highPriority = features(w)[]; processWidget(w, highPriority); // undefined…
条款5 相对显式类型声明,更倾向使用auto 基础知识 auto能大大方便变量的定义,可以表示仅由编译器知道的类型. template<typename It> void dwim(It b, It e) { while(b != e) { //typename std::iterator_traits<It>::value_type currValue = *b; // old type auto currValue = *b; // new type } } auto可以用来定…
条款四 知道如何看待推断出的类型 基础知识 有三种方式可以知道类型推断的结果: IDE编辑器 编译器诊断 运行时输出 使用typeid()以及std::type_info::name可以获取变量的类型信息,但是存在一些问题,代码如下: template<typename T> void f(const T& param) { using std::cout; cout << "T = " << typeid(T).name() <<…
条款三 了解decltype 基础知识 提供一个变量或者表达式,decltype会返回其类型,但是返回的内容会使人感到奇怪. 以下是一些简单的推断类型: ; // decltype(i) -> const int bool f(const Widget& w); // decltype(w) -> const Widget&, decltype(f) -> bool(const Widget&) struct Point { int x, y; } // decl…
条款二 了解auto类型推断 基础知识 除了一处例外,auto的类型推断与template一样.存在一个直接的从template类型推断到auto类型推断的映射 三类情况下的推断如下所示: // case 1 const auto& rx = x; // rx -> int // case 2 auto&& uref1 = x; // uref1 -> int& auto&& uref2 = cx; // uref2 -> const in…
条款一 了解模板类型推断 基本情况 首先定义函数模板和函数调用的形式如下,在编译期间,编译器推断T和ParamType的类型,两者基本不相同,因为ParamType常常包含const.引用等修饰符 template<typename T> void f(ParamType param); // 函数模板形式 f(expr); // 函数调用 存在T的类型即为expr类型的情况,如下T为int templat<typename T> void f(const T& param…
假设有一个接收universal references的模板函数foo,定义如下: template<typename T> void foo(T&& t) { cout << "foo(T&& t)" << endl; } 如果想对某些类型做特殊处理,写一个重载版本的foo,比如想对float类型做特殊处理,就写一个接收float类型的foo: void foo(float n) { cout << &q…
下面这段代码,如果调用func,按照C++的标准,程序会被终止(std::terminate) void func() { std::thread t([] { std::chrono::microseconds dua(); std::this_thread::sleep_for(dua); }); } 原因在于C++标准规定,std::thread的析构被调用时,std::thread必须是unjoinable的,否则std::terminate就会被调用. std::thread有两种状态…
采用何种工具来查看型别推导结果,取决于你在软件开发过程的哪个阶段需要该信息.主要研究三个可能的阶段:撰写代码阶段.编译阶段.运行时阶段. IDE编译器 IDE中的代码编译器通常会在你将鼠标指针选停止某个程序实体,如变量.形参.函数等时,显示出该实体的型别.例如以下这段代码: ; auto x = theAnswer; auto y = &theAnswer; IDE编译器很可能会显示出,x的型别推导结果是int,而y则是const int*. 而让这种方法奏效,代码就多多少少要处于一种可编译状态…
说起decltype,这是个古灵精怪的东西.对于给定的名字或表达式,decltype能告诉你该名字或表达式的型别.一般来说,它告诉你的结果和你预测的是一样的.不过,偶尔它也会给出某个结果,让你抓耳挠腮,不得不 去参考手册或在线FAQ页面求得一些启发. 先从一般案例讲起——就是那些不会引发意外的案例.与模板和auto的型别推导过程相反,decltype一般只会鹦鹉学舌,返回给定的名字或表达式的确切型别而已: ; //decltype(i)是const int bool f(const Widget…
在条款1中,我们已经了解了有关模板型别的推导的一切必要知识,那么也就意味着基本上了解了auto型别推导的一切必要知识. 因为,除了一个奇妙的例外情况,auto型别推导就是模板型别推导.尽管和模板型别推导打交道的是模板.函数和形参,auto和它们秋毫无犯,但并不影响上面的结论成立. 在条款1中,我们用来解释模板型别推导的函数模板形如: template<typename T> void f(ParamType param); 而一次调用形如: f(expr); //以某表达式调用f 在f的调用语…
成百上千的程序员都在向函数模板传递实参,并拿到了完全满意的结果,而这些程序员中却有很多对这些函数使用的型别是如何被推导出的过程连最模糊的描述都讲不出来. 但是当模板型别推导规则应用于auto语境时,它们不像应用于模板时那样符合直觉.所以了解作为auto基础的模板型别推导的方方面面就变得相当重要了. 本条款将说明这些推导过程.这里通过一段伪代码来说明,函数模板大致形如: template<typename T> void f(ParamType param); 而一次调用形如: f(expr);…
41:针对可复制的形参,在移动成本低且一定会被复制的前提下,考虑将其按值传递 class Widget { public: void addName(const std::string& newName) { names.push_back(newName); } void addName(std::string&& newName) { names.push_back(std::move(newName)); } … private: std::vector<std::st…