高效C++
hurricane&&storming
Not being impetuous
展开
-
Effective C++ 条款30_透彻了解 Inlining 的里里外外_非同凡响
Understand the ins and outs of inliningInline 函数,多棒的主意呀!它们看起来像函数,动作像函数,比宏好得多(见条款 2 ),可以调用它们又不需蒙受函数调用所招致的额外开销。更棒的是,你获得的比你想到的还多,因为 “ 免除函数调用成本 ” 只是故事的一部分而已。编译器最优机制通常被设计用来浓缩那些 “ 不含函数调用 ” 的代码,所以当你 inline 某个函数,或许编译器就因此有能力对它(函数本体)执行语境相关最优化。大部分编译器绝不会对着一个 “ outli原创 2020-11-24 20:12:49 · 170 阅读 · 0 评论 -
Effective C++ 条款29_为 “ 异常安全 ” 而努力是值得的_非同凡响
Strive for exception-safe code异常安全性(Exception safety)有几分像是……呃…怀孕。但等等,在我们完成求偶之前,实在无法确实地谈论生育。假设有个 class 用来表现夹带背景图案的 GUI 菜单单。这个 class 希望用于多线程环境,所以它有个互斥器(mutex)作为并发控制器(concurrency control)之用:class PrettyMenu {public: ... void changeBackground(std::istrea原创 2020-11-19 23:04:17 · 260 阅读 · 0 评论 -
Effective C++ 条款28_避免返回 handles 指向对象内部成分_非同凡响
Avoid returning ‘’ handles ‘’ to object internals假设你的程序涉及矩形。每个矩形由其左上角和右下角表示。为了让一个 Rectangle 对象尽可能小,你可能会决定不把定义矩形的这些点存放在 Rectangle 对象内,而是放在一个辅助的 struct 内再让 Rectangle 去指它:class Point {public: Point(int x, int y); ... void setX(int newVal); void setY(in原创 2020-11-11 22:44:51 · 199 阅读 · 0 评论 -
Effective C++ 条款27_尽量少做转型动作_非同凡响
Minimize castingC++ 规则的设计目标之一是,保证 “ 类型错误 ” 绝不可能发生。理论上如果你的程序很 “ 干净地 ” 通过编译,那么恭喜你,这表示它并不企图在任何对象上执行任何不安全、无意义、愚蠢荒谬的操作。不幸的是,转型(casts)破坏了类型转换系统(type system)。那可能导致任何种类的麻烦,有些容易辨识,有些则非常隐晦。在 C++ 中转型是一个你会想带着极大尊重去亲近的一个特性。旧式转型 类C风格:(T)expressionT(expression)C++原创 2020-11-09 22:21:01 · 158 阅读 · 0 评论 -
Effective C++ 条款26_尽可能延后变量定义式的出现时间_非同凡响
Postpone variable definitions as long as possible只要你定义了一个变量而其类型带有一个构造函数或析构函数,那么当程序的控制流(control flow)到达这个变量的定义式时,你便得承受构造成本;当这个变量离开其作用域时,你便得承受析构成本。即使这个变量最终并未被使用,仍需耗费这些成本,所以你应该尽可能避免这种情形。或许你会认为,你不可能定义一个不使用的变量,但话不要说的太早,看看下面这个函数,它计算通行密码的加密版本而后返回,前提是密码够长。如果密码太短原创 2020-11-07 20:07:36 · 365 阅读 · 1 评论 -
Effective C++ 条款25_考虑写出一个不抛异常的 swap 函数_不止于此
Consider support for a non-throwing swapswap 是个有趣的函数。原本它只是 STL 的一部分,而后成为异常安全性编程的脊柱,以及用来处理自我赋值可能性(见条款 11)的一个常见机制。由于 swap 如此有用,适当的实现很重要。然而在非凡的重要性之外它也带来了非凡的复杂度。本条款探讨这些复杂度及因应之道。所谓 swap (置换)两对象值,意思是将两对象的值彼此赋予对方。缺省情况下 swap 动作可由标准程序库提供的 swap 算法完成:namespace std原创 2020-11-03 21:14:29 · 203 阅读 · 1 评论 -
Effective C++ 条款24_若所有参数皆需类型转换,请为此采用 non-member 函数_不止于此
Declare non-member functions when type conversions should apply to all parameters令 classes 支持隐式类型转换通常是个糟糕的注意。当然这条规定则有其例外,最常见的例外是在建立数值类型时。假设你设计一个 class 用来表现有理数,允许整数 “ 隐式转换 ” 为有理数颇为合理。的确,它并不比 C++ 内置从 int 至double 的转换来得不合理,而还比 C++ 内置从 double 至 int 的转换来得合理些。原创 2020-11-01 16:02:47 · 143 阅读 · 0 评论 -
Effective C++ 条款23_宁以 non-member、non-friend 替换 member 函数_不止于此
Prefer non-member non-friend functions to member functions想象有个 class 用来表示网页浏览器。这样的 class 可能提供的众多函数中,有一些用来清除下载元素高速缓存区(cache of download elements)、清除访问过的 URLs 的历史记录(history of visited URLs)、以及移除系统中的所有cookies:class WebBrowser{public: ... void clearCache(原创 2020-10-31 14:00:50 · 177 阅读 · 0 评论 -
Effective C++ 条款22_将成员变量声明为 private_不止于此
Declare data members private先来看看 public 成员变量,为什么不采用它呢?如果成员变量不是 public,客户唯一能够访问对象的办法就是通过成员函数。使用函数处理变量有更精确的控制,毕竟不是每个成员变量都需要一个 getter 函数和 setter 函数。封装,便于日后更改维护代码。举个栗子,假设写一个自动测速程序,当汽车通过时,其速度便被计算并填入一个速度收集器里:class SpeedDataCollection{ ...public: void原创 2020-10-30 19:53:58 · 138 阅读 · 0 评论 -
Effective C++ 条款21_必须返回对象时,别妄想返回其reference_不止于此
Don’t try to return a reference when you must return an object原创 2020-10-29 20:02:57 · 153 阅读 · 0 评论 -
Effective C++ 条款20_宁以 pass-by-reference-to-const 替换 pass-by-value_不止于此
Prefer pass-by-reference-to-const to pass-by-value原创 2020-10-22 21:28:36 · 155 阅读 · 0 评论 -
Effective C++ 条款19_设计 class 犹如设计 type_不止于此
Treat class design as type designC++ 就像在其他 OOP (面向对象编程)语言一样,当你定义一个新的 class,也就定义了一个新的 type。身为 C++ 程序员,你的许多时间主要用来扩张你的类型系统。这意味你不是 class 设计者,而是 type 设计者。重载函数和操作符、控制内存分配和归还、定义对象的初始化和终结等等,完全都在你手上。如何设计高效的 classes 呢,了解你面对的问题,并从以下规范出发:新 type 的对象应该如何被创建和销毁?这会影原创 2020-10-20 14:59:16 · 133 阅读 · 0 评论 -
Effective C++ 条款18_让接口容易被正确使用,不易被误用_不止于此
Make interfaces easy to use correctly and hard to use incorrectlyC++ 在接口之海漂浮。function 接口、class 接口、template 接口…每一种接口都是客户与你的代码互动的手段。理想上,如果客户企图使用某个接口而却没有获得他所预期的行为,这个代码不应该通过编译;如果代码通过了编译,它的作为就该是客户想要的。欲开发一个 “ 容易被正确使用,不容易被误用 ” 的接口,首先必须考虑客户可能做出什么样的错误。假设你为一个用来表示原创 2020-10-19 21:03:09 · 133 阅读 · 0 评论 -
Effective C++ 条款17_不止于此
以独立语句将 newed 对象置入智能指针假设我们有个函数用来揭示处理程序的优先权,另一个函数用来在某动态分配所得的 Widget 上进行某些带有优先权的处理:int priority();void processWidget(std::tr1::shared_ptr<Widget> pw, int priority); // 声明由于谨记 “ 以对象管理资源 ” 的智慧铭言,processWidget 决定对其动态分配得来的 Widget 运用智慧指针(这里采用 tr1::shar原创 2020-10-18 10:44:02 · 228 阅读 · 0 评论 -
Effective C++ 条款16_不止于此
成对使用 new 和 delete 时要采取相同形式先看下面两行代码有什么错:std::string* stringArray = new std::string[100];...delete stringArray;看起来似乎还好,使用了 new 的同时在最后也使用了 delete,但还是有个致命的错误:程序行为不明确(未有定义)。最低限度,stringArray 所含的 100 个 string 对象中的 99 个不太可能被删除,因为它们的析构函数很可能没被调用。解释:当你使用 new原创 2020-10-17 11:50:47 · 149 阅读 · 0 评论 -
Effective C++ 条款15_不止于此
在资源管理类中提供对原始资源的访问资源管理类很好,它们是对抗资源泄露的堡垒。但许多 APIs 直接指涉资源,只得资源管理对象直接访问原始资源。举个例子,条款 13 导入一个观念:使用智能指针如 auto_ptr 或 tr1::shared_ptr 保存 factory 函数如 createInvestment 的调用结果:std::tr1::shared_ptr<Investment> pInv(createment()); // 见条款 13假设你希望以某个函数处理 Inv原创 2020-10-16 21:12:50 · 336 阅读 · 0 评论 -
Effective C++ 条款14_不止于此
在资源管理类中小心 copying 行为条款 13 导入这样的观念:“ 资源取得时机便是初始化时机 ” (Resource Acquisition Is Initialization;RAII),并以此作为 “ 资源管理类 ” 的脊柱,也描述了 auto_ptr 和 tr1::shared_ptr 如何将这个观念表现在 heap-based (基于堆)资源上。然而,并非所有的资源都是 heap-based,对于那些资源,上面那样的指挥指针往往并不适合作为资源掌管着。既然如此,我们有时候就需要建立自己的原创 2020-10-15 19:07:38 · 196 阅读 · 0 评论 -
Effective C++ 条款13_不止于此
以对象管理资源假设我们使用一个用来墅模投资行为(例如股票、债券等)的程序库,其中各种各样的投资类型继承自一个 root class Investment:class Investment { ... }; // root class进一步假设,这个程序库通过一个工厂函数(factory function)供应我们特定的 Investment 对象:Investment* createInvestment(); // 返回指针,指向Investment 继承体系内的动态分配对象。调用者有责任删原创 2020-10-14 21:47:21 · 409 阅读 · 7 评论 -
Effective C++ 条款12_不止于此
复制对象时勿忘其每一个成分设计良好之面向对象系统会将对象的内部封装起来,只留两个函数负责对象拷贝(copy 构造函数和 copy assignment 操作符)在 C++ 中,如果自己声明 copying 函数,会发生这样一种情况:当你的实现代码几乎必然出错时却不告诉你。看下面的代码说事:void logCall(const std::string& funcName); // 制造一个 log entryclass Customer {public: ... Customer(c原创 2020-10-13 13:00:24 · 249 阅读 · 0 评论 -
Effective C++ 条款11_不止于此
在 operator= 中处理 “自我赋值”“ 自我赋值 ” 发生在对象被赋值给自己时:class Getself { ... };Getself w;...w = w; // 赋值给自己 // 看起来似乎有些愚蠢,但不乏有人这样做还有一些潜在不容易看出来的自我赋值:a [ i ] = a [ j ]; // 潜在的自我赋值// 如果 i = j,那么便是自我赋值再看:*ptr = *qtr; // 潜在的自我赋值// 如果 ptr 和 qtr 都指向同一个原创 2020-10-12 20:03:38 · 205 阅读 · 0 评论 -
Effective C++ 条款10_不止于此
令 operator= 返回一个 reference to *this关于赋值int x, y, z;x = y = z = 4; // 赋值连锁形式赋值采用右结合律,所以上述连锁被解析为:x = ( y = ( z = 4 ) );就是 4 先赋值给 z,然后 z 的值再赋值给 y,更新 y 的值在赋值给 x。为了实现连锁赋值,赋值操作符必须返回一个 reference 指向操作符的左侧实参。这是你为 classes 实现赋值操作符是应遵循的协议:class Assign {pu原创 2020-10-11 10:50:04 · 184 阅读 · 0 评论 -
Effective C++ 条款09_不止于此
绝不在构造和析构过程中调用 virtual 函数假设有个 class 继承体系,用以墅模股市交易如买进、卖出的订单等等。这样的交易一定需要经过审计,所以每当创建一个交易对象,在审计日志中也需要创建一笔适当记录:class Transaction { // 所有交易的 base classpublic: Transaction (); virtual void logTransaction() const = 0; // 做出一份因类型不同而不同的日志记录 ...};Transacti原创 2020-10-10 21:31:00 · 350 阅读 · 0 评论 -
Effective C++ 条款08_不止于此
别让异常逃离析构函数C++ 并不禁止析构函数吐出异常,但它也不鼓励这样做。考虑下面代码:class Widget {public: ... ~Widget( ) {...} // 假设这里吐出一个异常};void soSomething(){ std::vector<Widget> vec; ...} // vec 在这里被自动销毁当 vector vec 被销毁,它有责任销毁其内含的所有 Widgets。假设 vec 内含10个Widgets,而在析构第一个原创 2020-10-09 23:58:06 · 201 阅读 · 0 评论 -
Effective C++ 条款07_不止于此
为多态基类声明 virtual 析构函数举个例子有许多种方法可以记录时间,因此,设计一个 TimeTracer base class 和一些 derived classes 作为不同的计时方法比较方便:class TimeTracer {public: TimeTracer(){...}; ~TimeTracer(){...};};class AtomicClock: public: TimeTracer{...}; // 原子钟class WaterClock: public:原创 2020-10-08 21:46:37 · 487 阅读 · 0 评论 -
Effective C++ 条款06_不止于此
若不想使用编译器自动生成的函数,就该明确拒绝eg:假设有个天生第一无二的 class,它所创建的对象绝不允许被拷贝。class HomeLord { ... }; // 假设这个创建的对象不想被拷贝一份HomeLord h1;HomeLord h2;HomeLord h3(h1); // 企图调用 copy 构造函数拷贝 h1,应该被编译器拒绝,不该通过编译HomeLord h4 = h2; // 企图调用 copy assignment 操作符拷贝 h2,应该被编译器拒绝,不该通过编译原创 2020-10-07 17:35:42 · 652 阅读 · 0 评论 -
Effective C++ 条款05_不止于此
了解C++ 默默编写并调用哪些函数先来看看一个空类class Empty{ }; // 空类当有对象被创建出来调用这些函数的时候 C++ 就会产出下面这些函数 :class Empty {public: Empty(){...}; //默认(default )构造函数 Empty(const Empty& params){...}; // 拷贝(copy)构造函数 ~Empty(){...}; //析构函数 Empty& operator=原创 2020-10-06 19:43:45 · 198 阅读 · 0 评论 -
Effective C++ 条款04_不止于此
确定对象被使用前已先被初始化像下面这样:int x; // x其实也可以认为是一个对象一个实例就是一个对象 class A{ int a; }; A a;在某些情况下x被初始化为0;a的成员变量也被初始化为0。但有时候是不确定的,就会有使用了但没被初始化的情况造成无法挽救的影响,有时候会直接使程序崩掉并不知所以,所以好的程序设计应该像下面这样:int x = 0; / / 定义并初始化class A{int x = 0, y = 0; / / 定义并初始化}原创 2020-10-05 20:56:15 · 324 阅读 · 0 评论 -
Effective C++ 条款03_不止于此
尽可能使用const首先明确 : const量不可变, * 代表被指的数据,名字代表指针地址char gre[] = "Hello";char *ptr = "Hello"; //前面讲过不如 char std::string ptr = "Hello" //这是只是演示const char* ptr = Hello; //常数据,非常指针char* const ptr = Hello; //常指针,非常数据const char* const ptr = Hello;//常指针原创 2020-10-04 15:31:12 · 361 阅读 · 0 评论 -
Effective C++ 条款02_不止于此
尽量以const,enum,inline替换 #defineeg:#define Apple_Line 3.5 //运行时如果是此常量报错只会提示3.5而不是Apple如果Apple被定义在一个非你所写的头文件中将导致你很难找出bug解决方案:const double Apple = 3.5;另外说说,定义常指针,倘若指针常量不变则写两遍const,通常被写在头文件中const char* const chName = "bobobo";但是不如用std::stringcons原创 2020-10-03 22:36:45 · 1186 阅读 · 0 评论 -
Effective C++ 条款01_不止于此
Effective C++条款01:视C++为一个语言联邦C++是四个次语言(C、Object-Oriented C++、Template C++、STL)组成的联邦政府请记住:C++高效编程守则视情况而变化原创 2020-10-03 21:28:04 · 154 阅读 · 0 评论