Scott Meyers系列
文章平均质量分 79
Effective C++
More Effective C++
Effective Modern C++
Scott Meyers的三部曲学习笔记
C咖咖
历史不会简单的重复,但历史会惊人的相似
展开
-
Effective Modern C++ 之 条款6:当auto推导出非预期类型时应当使用 显式的类型初始化
条款5解释了使用 auto 关键字去声明变量,这样就比直接显示声明类型提供了一系列的技术优势,但是有时候 auto 的类型推导会和你想的南辕北辙。举一个例子,假设我有一个函数接受一个 Widget 返回一个 std::vector<bool> ,其中每个 bool 表征 Widget 是否接受一个特定的特性:std::vector<bool> features(con...原创 2019-11-27 10:33:09 · 220 阅读 · 0 评论 -
Effective Modern C++ 之 条款五:优先使用 auto 而非显式类型声明
使用下面语句是简单快乐的int x;等等。见鬼,我忘记初始化 x ,因此它的值是无法确定的。也许,它会被初始化为0。但是这根据上下文语境决定。这真令人叹息。不要介意。我们来看看一个要通过迭代器解引用初始化的局部变量声明的简单与快乐。template<typename It>void dwim(It b, It e){ while(b != e) ...原创 2019-11-25 10:16:46 · 304 阅读 · 0 评论 -
Effective Modern C++ 之 条款三:理解 decltype
decltype 是一个怪异的发明。给定一个变量名或者表达式, decltype 会告诉你这个变量名或表达式的类型。 decltype 的返回的类型往往也是你期望的。然而有时候,它提供的结果会使开发者极度抓狂而不得参考其他文献或者在线的Q&A网站。我们从在典型的情况开始讨论,这种情况下 decltype 不会有令人惊讶的行为。与 templates 和 auto 在类型推导中行为相比(...原创 2019-11-24 10:27:16 · 209 阅读 · 0 评论 -
Effective Modern C++ 之 条款二:理解 auto 类型推导
如果你已经阅读了条款1关于模板相关的类型推导,你就已经知道了机会所有关于 auto 的类型推导,因为除了一个例外, auto 类型推导就是模板类型推导。但是它怎么就会是模板类型推导呢?模板类型推导涉及模板和函数以及参数,但是 auto 和上面的这些没有任何的关系。这是对的,但是没有关系。模板类型推导和 auto 类型推导是有一个直接的映射。有一个书面上的从一种情况转换成另外一种情况的算法。在...原创 2019-11-24 10:12:09 · 440 阅读 · 0 评论 -
Effective Modern C++ 之 条款1:理解模板类型推导
Understand template type deduction. 当一个复杂系统的用户忽略这个系统是如何工作的,那就再好不过了,因为“如何”扯了一堆系统的设计细节。从这个方面来度量,C++的模板类型推导是个巨大的成功。成百上万的程序猿给模板函数传递完全类型匹配的参数,尽管有很多的程序猿会更加苛刻的给于这个函数推导的类型的严格描述。 如果上面的描述包括你,那我有好消息也有坏...原创 2019-11-21 07:46:28 · 496 阅读 · 0 评论 -
More Effective C++之 Item M35:让自己习惯使用标准C++语言
自1990年出版以来,《The Annotated C++ Reference Manual 》(见原书P285,附录:推荐读物)是最权威的参考手册供程序员们判断什么是C++拥有的而什么不是。在它出版后的这些年来,C++的ISO/ANSI标准已经发生了大大小小的变化了(主要是扩充)。作为权威手册,它已经不适用了。在《ARM》之后C++发生的变化深远地影响了写出的程序的优良程度。因此,对程序员...原创 2019-11-21 07:39:21 · 141 阅读 · 0 评论 -
More Effective C++之 Item M34:如何在同一程序中混合使用C++和C
许多年来,你一直担心编制程序时一部分使用C++一部分使用C,就如同在全部用C编程的年代同时使用多个编译器来生成程序一样。没办法多编译器编程的,除非不同的编译器在与实现相关的特性(如int和double的字节大小,传参方式)上相同。但这个问题在语言的标准化中被忽略了,所以唯一的办法就是两个编译器的生产商承诺它们间兼容。C++和C混合编程时同样是这个问题,所以在实体混合编程前,确保你的C++编译器和...原创 2019-11-21 07:38:35 · 180 阅读 · 0 评论 -
More Effective C++之 Item M33:将非尾端类设计为抽象类
假设你正在从事一个软件项目,它处理动物。在这个软件里,大多数动物能被抽象得非常类似,但两种动物--晰蜴和小鸡--需要特别处理。显然,晰蜴和小鸡与动物类的联系是这样的:动物类处理所有动物共有的特性,晰蜴类和小鸡类特别化动物类以适用这两种动物的特有行为。这是它们的简化定义:class Animal {public: Animal& operator=(con...原创 2019-11-14 17:50:40 · 204 阅读 · 0 评论 -
More Effective C++之 Item M32:在未来时态下开发程序
事物在变化。作为软件开发人员,我们也许知道得不多,但我们知道万物都会变化。我们没必要知道什么将发生变化,这么变化又怎么发生,以什么时候发生,在哪里发生,但我们知道:万物都会变化。好的软件能够适应变化。它提供新的特性,适应到新的平台,满足新的需求,处理新的输入。软件的灵活性、健壮性、可靠性不是来自于意外。它是程序员们在满足了现在的需求并关注了将来的可能后设计和实现出来的。这样的软件(接受小...原创 2019-11-14 17:48:07 · 172 阅读 · 0 评论 -
More Effective C++之 Item M31:让函数根据一个以上的对象来决定怎么虚拟
有时,借用一下Jacqueline Susann的话:一次是不够的。例如你有着一个光辉形象、崇高声望、丰厚薪水的程序员工作,在Redmond,Wshington的一个著名软件公司--当然,我说的就是任天堂。为了得到经理的注意,你可能决定编写一个video game。游戏的背景是发生在太空,有宇宙飞船、太空站和小行星。在你构造的世界中的宇宙飞船、太空站和小行星,它们可能会互相碰撞。假设其规则是...原创 2019-11-14 17:43:20 · 860 阅读 · 0 评论 -
More Effective C++之 Item M30:代理类
虽然你和你的亲家可能住在同一地理位置,但就整个世界而言,通常不是这样的。很不幸,C++还没有认识到这个事实。至少,从它对数组的支持上可以看出一些迹象。在FORTRAN、BASIC甚至是COBOL中,你可以创二维、三维乃至n维数组(OK,FORTRAN只能创最多7维数组,但别过于吹毛求疵吧)。但在C++中呢?只是有时可以,而且也只是某种程度上的。这是合法的:int data[10][20]...原创 2019-11-14 17:29:52 · 175 阅读 · 0 评论 -
More Effective C++之 Item M29:引用计数
引用计数是这样一个技巧,它允许多个有相同值的对象共享这个值的实现。这个技巧有两个常用动机。第一个是简化跟踪堆中的对象的过程。一旦一个对象通过调用new被分配出来,最要紧的就是记录谁拥有这个对象,因为其所有者--并且只有其所有者--负责对这个对象调用delete。但是,所有权可以被从一个对象传递到另外一个对象(例如通过传递指针型参数),所以跟踪一个对象的所有权是很困难的。象auto_ptr(见Ite...原创 2019-11-14 17:15:09 · 272 阅读 · 0 评论 -
More Effective C++之 Item M28:灵巧(smart)指针
灵巧指针是一种外观和行为都被设计成与内建指针相类似的对象,不过它能提供更多的功能。它们有许多应用的领域,包括资源管理(参见条款M9、M10、M25和M31)和重复代码任务的自动化(参见条款M17和M29)。当你使用灵巧指针替代C++的内建指针(也就是dumb pointer),你就能控制下面这些方面的指针的行为:l 构造和析构。你可以决定建立灵巧指针时应该怎么做。通常赋给...原创 2019-11-14 16:39:42 · 269 阅读 · 0 评论 -
More Effective C++之 Item M27:要求或禁止在堆中产生对象
有时你想这样管理某些对象,要让某种类型的对象能够自我销毁,也就是能够“delete this”。很明显这种管理方式需要此类型对象被分配在堆中。而其它一些时候你想获得一种保障:“不在堆中分配对象,从而保证某种类型的类不会发生内存泄漏。”如果你在嵌入式系统上工作,就有可能遇到这种情况,发生在嵌入式系统上的内存泄漏是极其严重的,其堆空间是非常珍贵的。有没有可能编写出代码来要求或禁止在堆中产生对象(he...原创 2019-11-14 16:03:06 · 189 阅读 · 0 评论 -
More Effective C++之 Item M26:限制某个类所能产生的对象数量
很痴迷于对象,但是有时你又想束缚住你的疯狂。例如你在系统中只有一台打印机,所以你想用某种方式把打印机对象数目限定为一个。或者你仅仅取得16个可分发出去的文件描述符,所以应该确保文件描述符对象存在的数目不能超过16个。你如何能够做到这些呢?如何去限制对象的数量呢? 如果这是一个用数学归纳法进行的证明,你会从n=1开始证明,然后从此出发推导出其它证明。幸运的是这既不是一个证明也不是一个归纳...原创 2019-11-14 14:56:02 · 178 阅读 · 0 评论 -
More Effective C++之 Item M25:将构造函数和非成员函数虚拟化
从字面来看,谈论“虚拟构造函数”没有意义。当你有一个指针或引用,但是不知道其指向对象的真实类型是什么时,你可以调用虚拟函数来完成特定类型(type-specific)对象的行为。仅当你还没拥有一个对象但是你又确切地知道想要的对象的类型时,你才会调用构造函数。那么虚拟构造函数又从何谈起呢? 很简单。尽管虚拟构造函数看起来好像没有意义,其实它们有非常大的用处(如果你认为没有意义的想法就没有...原创 2019-11-14 14:41:06 · 133 阅读 · 0 评论 -
More Effective C++之 Item M24:理解虚拟函数、多继承、虚基类和RTTI所需的代价
C++编译器们必须实现语言的每一个特性。这些实现的细节当然是由编译器来决定的,并且不同的编译器有不同的方法实现语言的特性。在多数情况下,你不用关心这些事情。然而有些特性的实现对对象大小和其成员函数执行速度有很大的影响,所以对于这些特性有一个基本的了解,知道编译器可能在背后做了些什么,就显得很重要。这种特性中最重要的例子是虚拟函数。当调用一个虚拟函数时,被执行的代码必须与调用函数...原创 2019-11-14 13:54:37 · 180 阅读 · 0 评论 -
More Effective C++之 Item M23:考虑变更程序库
程序库的设计就是一个折衷的过程。理想的程序库应该是短小的、快速的、强大的、灵活的、可扩展的、直观的、普遍适用的、具有良好的支持、没有使用约束、没有错误的。这也是不存在的。为尺寸和速度而进行优化的程序库一般不能被移植。具有大量功能的的程序库不会具有直观性。没有错误的程序库在使用范围上会有限制。真实的世界里,你不能拥有每一件东西,总得有付出。 不同的设计者给这些条件赋予了不同的优先级。他们...原创 2019-11-13 07:52:32 · 123 阅读 · 0 评论 -
More Effective C++之 Item M22:考虑用运算符的赋值形式(op=)取代其单独形式(op)
大多数程序员认为如果他们能这样写代码:x = x + y; x = x - y; 那他们也能这样写:x += y; x -= y; 如果x和y是用户定义的类型(user-defined type),就不能确保这样。就C++来说,operator+、operator=和operator+=...原创 2019-11-13 07:51:58 · 124 阅读 · 0 评论 -
More Effective C++之 Item M21:通过重载避免隐式类型转换
以下是一段代码,如果没有什么不寻常的原因,实在看不出什么东西:class UPInt { // unlimited precisionpublic: // integers 类 UPInt(); UPInt(int value); ...原创 2019-11-13 07:51:24 · 127 阅读 · 0 评论 -
More Effective C++之 Item M20:协助完成返回值优化
一个返回对象的函数很难有较高的效率,因为传值返回会导致调用对象内的构造和析构函数(参见条款M19),这种调用是不能避免的。问题很简单:一个函数要么为了保证正确的行为而返回对象要么就不这么做。如果它返回了对象,就没有办法摆脱被返回的对象。就说到这。考虑rational(有理数)类的成员函数operator*:class Rational {public: Rational(int...原创 2019-11-13 07:50:50 · 144 阅读 · 0 评论 -
More Effective C++之 Item M19:理解临时对象的来源
当程序员之间进行交谈时,他们经常把仅仅需要一小段时间的变量称为临时变量。例如在下面这段swap(交换)例程里:template<class T>void swap(T& object1, T& object2){ T temp = object1; object1 = object2; object2 = temp;} 通常...原创 2019-11-13 07:48:47 · 154 阅读 · 0 评论 -
More Effective C++之 Item M18:分期摊还期望的计算
在条款M17中,我极力称赞懒惰的优点,尽可能地拖延时间,并且我解释说懒惰如何提高程序的运行效率。在这个条款里我将采用一种不同的态度。这里将不存在懒惰。我鼓励你让程序做的事情比被要求的还要多,通过这种方式来提高软件的性能。这个条款的核心就是over-eager evaluation(过度热情计算法):在要求你做某些事情以前就完成它们。例如下面这个模板类,用来表示放有大量数字型数据的一个集合:t...原创 2019-11-13 07:48:14 · 165 阅读 · 0 评论 -
More Effective C++之 Item M17:考虑使用lazy evaluation(懒惰计算法)
从效率的观点来看,最佳的计算就是根本不计算,那好,不过如果你根本就不用进行计算的话,为什么还在程序开始处加入代码进行计算呢?并且如果你不需要进行计算,那么如何必须执行这些代码呢? 关键是要懒惰。 还记得么?当你还是一个孩子时,你的父母叫你整理房间。你如果象我一样,就会说“好的“,然后继续做你自己的事情。你不会去整理自己的房间。在你心里整理房间被排在了最后的位置,实际上直到你听...原创 2019-11-13 07:47:35 · 276 阅读 · 0 评论 -
More Effective C++之 Item M16:牢记80-20准则(80-20 rule)
80-20准则说的是大约20%的代码使用了80%的程序资源;大约20%的代码耗用了大约80%的运行时间;大约20%的代码使用了80%的内存;大约20%的代码执行80%的磁盘访问;80%的维护投入于大约20%的代码上;通过无数台机器、操作系统和应用程序上的实验这条准则已经被再三地验证过。80-20准则不只是一条好记的惯用语,它更是一条有关系统性能的指导方针,它有着广泛的适用性和坚实的实验基础。...原创 2019-11-13 07:46:57 · 147 阅读 · 0 评论 -
More Effective C++之 Item M15:了解异常处理的系统开销
为了在运行时处理异常,程序要记录大量的信息。无论执行到什么地方,程序都必须能够识别出如果在此处抛出异常的话,将要被释放哪一个对象;程序必须知道每一个入口点,以便从try块中退出;对于每一个try块,他们都必须跟踪与其相关的catch子句以及这些catch子句能够捕获的异常类型。这种信息的记录不是没有代价的。虽然确保程序满足异常规格不需要运行时的比较(runtime comparisons),而且...原创 2019-11-13 07:46:25 · 89 阅读 · 0 评论 -
More Effective C++之 Item M14:审慎使用异常规格(exception specifications
毫无疑问,异常规格是一个引人注目的特性。它使得代码更容易理解,因为它明确地描述了一个函数可以抛出什么样的异常。但是它不只是一个有趣的注释。编译器在编译时有时能够检测到异常规格的不一致。而且如果一个函数抛出一个不在异常规格范围里的异常,系统在运行时能够检测出这个错误,然后一个特殊函数unexpected将被自动地调用。异常规格既可以做为一个指导性文档同时也是异常使用的强制约束机制,它好像有着很诱人...原创 2019-11-12 09:28:05 · 193 阅读 · 0 评论 -
More Effective C++之 Item M13:通过引用(reference)捕获异常
当你写一个catch子句时,必须确定让异常通过何种方式传递到catch子句里。你可以有三个选择:与你给函数传递参数一样,通过指针(by pointer),通过传值(by value)或通过引用(by reference)。 我们首先讨论通过指针方式捕获异常(catch by pointer)。从throw处传递一个异常到catch子句是一个缓慢的过程,在理论上这种方法的实现对于这个过程...原创 2019-11-12 09:27:20 · 187 阅读 · 0 评论 -
More Effective C++之 Item M12:理解“抛出一个异常”与“传递一个参数”或“调用一个虚函数”间的差异
从语法上看,在函数里声明参数与在catch子句中声明参数几乎没有什么差别:class Widget { ... }; //一个类,具体是什么类 // 在这里并不重要void f1(Widget w); // 一些函数,其参数分别为void f2(W...原创 2019-11-12 09:19:15 · 164 阅读 · 0 评论 -
More Effective C++之 Item M11:禁止异常信息(exceptions)传递到析构函数外
在有两种情况下会调用析构函数。第一种是在正常情况下删除一个对象,例如对象超出了作用域或被显式地delete。第二种是异常传递的堆栈辗转开解(stack-unwinding)过程中,由异常处理系统删除一个对象。 在上述两种情况下,调用析构函数时异常可能处于激活状态也可能没有处于激活状态。遗憾的是没有办法在析构函数内部区分出这两种情况。因此在写析构函数时你必须保守地假设有异常被激活。因为如...原创 2019-11-12 09:11:46 · 158 阅读 · 0 评论 -
More Effective C++之 Item M10:在构造函数中防止资源泄漏
如果你正在开发一个具有多媒体功能的通讯录程序。这个通讯录除了能存储通常的文字信息如姓名、地址、电话号码外,还能存储照片和声音(可以给出他们名字的正确发音)。 为了实现这个通信录,你可以这样设计:class Image { // 用于图像数据public: Image(const string& imageDataFil...原创 2019-11-12 09:10:25 · 152 阅读 · 0 评论 -
More Effective C++之 Item M9:使用析构函数防止资源泄漏
对指针说再见。必须得承认:你永远都不会喜欢使用指针。 Ok,你不用对所有的指针说再见,但是你需要对用来操纵局部资源(local resources)的指针说再见。假设,你正在为一个小动物收容所编写软件,小动物收容所是一个帮助小狗小猫寻找主人的组织。每天收容所建立一个文件,包含当天它所管理的收容动物的资料信息,你的工作是写一个程序读出这些文件然后对每个收容动物进行适当的处理(approp...原创 2019-11-12 09:09:23 · 151 阅读 · 0 评论 -
More Effective C++之 Item M8:理解各种不同含义的new和delete
人们有时好像喜欢故意使C++语言的术语难以理解。比如说new操作符(new operator)和new操作(operator new)的区别。 当你写这样的代码:string *ps = new string("Memory Management");你使用的new是new操作符。这个操作符就象sizeof一样是语言内置的,你不能改变它的含义,它的功能总是一样的。它要完成的功能...原创 2019-11-12 09:08:36 · 135 阅读 · 0 评论 -
More Effective C++之 Item M7:不要重载“&&”,“||”, 或“,”
与C一样,C++使用布尔表达式短路求值法(short-circuit evaluation)。这表示一旦确定了布尔表达式的真假值,即使还有部分表达式没有被测试,布尔表达式也停止运算。例如:char *p;...if ((p != 0) && (strlen(p) > 10)) ...这里不用担心当p为空时strlen无法正确运行,因为如果p不等于0的测试失败...原创 2019-11-12 08:42:38 · 143 阅读 · 0 评论 -
More Effective C++之 Item M6:自增(increment)、自减(decrement)操作符前缀形式与后缀形式的区别
很久以前(八十年代),没有办法区分++和--操作符的前缀与后缀调用。这个问题遭到程序员的报怨,于是C++语言得到了扩展,允许重载increment 和 decrement操作符的两种形式。 然而有一个句法上的问题,重载函数间的区别决定于它们的参数类型上的差异,但是不论是increment或decrement的前缀还是后缀都只有一个参数。为了解决这个语言问题,C++规定后缀形式有一个in...原创 2019-11-12 08:42:08 · 791 阅读 · 0 评论 -
More Effective C++之 Item M5:谨慎定义类型转换函数
C++编译器能够在两种数据类型之间进行隐式转换(implicit conversions),它继承了C语言的转换方法,例如允许把char隐式转换为int和从short隐式转换为double。因此当你把一个short值传递给准备接受double参数值的函数时,依然可以成功运行。C中许多这种可怕的转换可能会导致数据的丢失,它们在C++中依然存在,包括int到short的转换和double到char的...原创 2019-11-12 08:41:27 · 132 阅读 · 0 评论 -
More Effective C++之 Item M4:避免无用的缺省构造函数
缺省构造函数(指没有参数的构造函数)在C++语言中是一种让你无中生有的方法。构造函数能初始化对象,而缺省构造函数则可以不利用任何在建立对象时的外部数据就能初始化对象。有时这样的方法是不错的。例如一些行为特性与数字相仿的对象被初始化为空值或不确定的值也是合理的,还有比如链表、哈希表、图等等数据结构也可以被初始化为空容器。 但不是所有的对象都属于上述类型,对于很多对象来说,不利用外部数据进...原创 2019-11-11 07:47:20 · 189 阅读 · 0 评论 -
More Effective C++之 Item M3:不要对数组使用多态
类继承的最重要的特性是你可以通过基类指针或引用来操作派生类。这样的指针或引用具有行为的多态性,就好像它们同时具有多种形态。C++允许你通过基类指针和引用来操作派生类数组。不过这根本就不是一个特性,因为这样的代码几乎从不如你所愿地那样运行。假设你有一个类BST(比如是搜索树对象)和继承自BST类的派生类BalancedBST:class BST { ... };class Balanc...原创 2019-11-11 07:46:45 · 109 阅读 · 0 评论 -
More Effective C++之 Item M2:尽量使用C++风格的类型转换
仔细想想地位卑贱的类型转换功能(cast),其在程序设计中的地位就象goto语句一样令人鄙视。但是它还不是无法令人忍受,因为当在某些紧要的关头,类型转换还是必需的,这时它是一个必需品。不过C风格的类型转换并不代表所有的类型转换功能。一来它们过于粗鲁,能允许你在任何类型之间进行转换。不过如果要进行更精确的类型转换,这会是一个优点。在这些类型转换中存在着巨大的不同,例如把一个指向const对...原创 2019-11-11 07:45:09 · 173 阅读 · 0 评论 -
More Effective C++之 Item M1:指针与引用的区别
指针与引用看上去完全不同(指针用操作符“*”和“->”,引用使用操作符“. ”),但是它们似乎有相同的功能。指针与引用都是让你间接引用其他对象。你如何决定在什么时候使用指针,在什么时候使用引用呢?首先,要认识到在任何情况下都不能使用指向空值的引用。一个引用必须总是指向某些对象。因此如果你使用一个变量并让它指向一个对象,但是该变量在某些时候也可能不指向任何对象,这时你应该把变量声明为指针...原创 2019-11-11 07:44:26 · 103 阅读 · 0 评论