
Effective C++
子建莫敌
热爱生活,拥抱技术
展开
-
Item30 透彻了解inlining的里里外外
inline,看起来像函数,可以调用它们又不需要一般函数调用的开销。inline的理念:对此函数的每一个调用都以函数本体替换。inline声明方式:隐喻声明:在类声明的.h中定义并实现 明确声明:在函数定义式前加上关键字“inline”inline函数通常一定被置于头文件内,因为大多数构建(build)环境在编译过程中进行inlining。为了将一个函数调用替换为被调用函数的本体,编译器必须知道函数内容。inline函数无法随函数库的升级而升级,即inline函数被改变,之前所有调用的程原创 2020-07-24 00:20:58 · 236 阅读 · 0 评论 -
Item29 为“”异常安全”而努力是值得的
“异常安全”的两个条件:不泄露任何资源: 不允许数据变坏异常安全函数提供以下三个保证之一:基本保证:如果异常被抛出,程序内任何事物仍然保持在有效状态下。 强烈保证:如果异常被跑出,程序状态不改变。copy and swap策略(拷贝一份,对副本修改,再设置回去)。 不抛掷保证:承诺绝不跑出异常。强烈保证,往往能够以copy-and-swap实现出来,但并非对所有的函数都可实现或具备现实意义。...原创 2020-07-24 00:00:48 · 133 阅读 · 0 评论 -
Item28 避免返回handles指向对象内部成分
通常,对象的内部就是指它的成员变量、私有或被保护的成员函数等。函数返回一个handle代表对象内部成分总是危险的,容易出现(对象)空悬、虚吊。成员变量的封装性最多只等于“返回其引用”的函数的访问级别 如const成员函数传出一个指针、引用、迭代器,后者所指数据与对象自身有关联,而它又被存储于对象之外,那么这个函数的调用者可以修改该数据。...原创 2020-07-22 00:04:58 · 145 阅读 · 0 评论 -
Item26 尽可能延后变量定义式的出现时间
只要定义了一个变量而其类型带有一个构造函数或析构函数,那么程序的控制流到达这个变量定义式时,便得承受构造成本;当这个变量离开作用域时,便承受析构成本。即使变量最终还是未被使用,仍需要耗费这些成本。注:延后定义,防止变量未被使用; 声明变量,赋初始,防止调用默认构造函数再赋值的开销; 涉及到循环操作,有2种写法的成本:1个构造函数 + 1个析构函数 + n个赋值操作 n个构造函数 + n个析构函数总之,尽可能延后变量定义式的出现,增加程序的清晰度并改善程序效率。...原创 2020-07-19 17:02:24 · 147 阅读 · 0 评论 -
Item25 考虑写出一个不抛出异常的swap函数
swap函数,原本只是STL的一部分,后来成为异常安全性编程的脊柱,以及用来处理自我赋值可能性的一个常见机制。典型实现:namespace std { template<typename T> void swap(T& a, T& b) { T temp(a); a = b; b = temp; }};如指针指向一个对象,内含真正数据,这种设计常见表现形式就是所谓的“pImpl”手法。原创 2020-07-19 16:48:33 · 181 阅读 · 0 评论 -
Item24 若所有参数都需要类型转换,请为此采用non-member函数
让class支持隐式转换,通常是个糟糕的主意。但需要建立数值类型时,还是需要允许隐式转换。原创 2020-07-19 15:57:01 · 168 阅读 · 0 评论 -
Item23 宁以non-member,non-friend替换member
面向对象守则要求数据应该尽可能封装,愈多函数可访问它,数据的封装性就愈低,故成员函数封装性差。在很多方面,非成员做法比成员做法好。通常,可以令成员函数为一个static函数,或让成员函数位于类同级的namespace下。如:namespace WebBrowserStuff { class WebBrowser{...}; void clearBrowser(WebBrowser& wb);};将所有便利函数放在多个头文件内但隶属同一个命名空间,意味客户可以轻松原创 2020-07-18 23:25:53 · 148 阅读 · 0 评论 -
Item22 将成员变量声明为private
如果成员变量不是public,对客户隐藏成员原量,那么唯一能够访问对象的办法就是通过成员函数。确保class的约束条件总是会获得维护,因为只有成员函数可以影响他们。将成员变量申明为private,这可具有语法的一致性、更精确的访问控制、封装、提供class作者充分的实现弹性等优点 protected并不比public更有封装性...原创 2020-07-18 22:59:48 · 137 阅读 · 0 评论 -
Item19 设计class犹如设计type
C++ 同其他OOP(面向对象)语言一样,定义一个新class,也就定义了一个新的type。设计规范:新type的对象应该如何被创建和销毁 对象的初始化和对象的赋值该有什么样的区别 新type的对象如被passed by value(传值),意味着什么 新type的合法值 新type需要配合某个继承图系 新type需要什么样的转换 什么样的操作符合函数对此新type而言合理 什么样的标准函数应该驳回(必须声明为private) 谁该取用新type的成员 什么是新type的未声明接口原创 2020-07-18 22:45:34 · 135 阅读 · 0 评论 -
Item18 让接口容易被正确使用,不易被误用
C++接口:function接口 class接口 template接口“容易被正确使用,不容易被误用”接口设计准则:必须考虑调用方可能做出的错误尽量令接口类型的相关行为与既有内置类型一致。“促进正确使用”的办法包括接口的一致性,以及与内置类型的行为兼容;“防治误用”的办法包括建立新类型,限制类型上的操作,束缚对象值,以及消除用户的资源管理责任 tr1::shared_ptr支持定制型删除器,可预防DLL问题,可被用来自动解除互斥锁等等...原创 2020-07-18 00:02:22 · 136 阅读 · 0 评论 -
Item6 若不想使用编译器自动生成的函数,就该明确拒绝
Item5中提到:基类如果把类内默认函数(构造或copy assignment操作符)设置为private,子类将拒绝生成。但这并不绝对安全。因为成员函数和友元函数还是可以调用private函数。这里提供一种方案:在类中声明为private,但不去实现。实现上,可以定义一个专门未来阻止该操作的基类。如:阻止对象呗拷贝的Uncopyable基类:class UnCopyable {protected: UnCopyable() {} ~UnCopyable() {}p原创 2020-07-17 23:50:09 · 195 阅读 · 0 评论 -
Item5 了解C++默默编写并调用了哪些函数
如果自己不声明, 编译器就会暗自为class创建一个default构造函数、一个copy构造函数、一个copy assignment操作符(代码合法有意义时编译器才会生成),以及一个析构函数class Empty { };对应地有class Empty {public: Empty(){...} Empty(const Empty& rhs) {...} ~Empty(){...} Empty& operator=(const Empty&原创 2020-07-17 23:37:04 · 178 阅读 · 0 评论 -
Item4 确认对象被使用前已先被初始化
读取未初始化的值会导致不明确的行为。规则:确保每个构造函数都将对象的每一个成员初始化。为内置型对象进行手工初始化;内置类型以外,构造函数负责初始化责任。赋值和初始化构造函数内的利用传递的参数给成员赋值的操作,为赋值;初始化列表,为初始化; 两者效果一样,但初始化列表效率更高。因为赋值手续调用默认构造函数为成员设初值,然后再赋值; 如果成员变量是const常量或引用类型,必须使用初始化列表赋值; 初始化顺序,为变量声明顺序...原创 2020-07-16 23:51:10 · 176 阅读 · 0 评论 -
Item3 尽可能使用const
const多才多艺,告诉编译器和其他程序员某值应该保持不变。可以用在class外部修饰global或namespace作用域中的常量,修饰文件,函数,或static对象。char greeting[] = "hello";char* p = greeting; //non-const pointer, non-const dataconst char* p = greeting; // non-const pointer, const datachar* const p = greet原创 2020-07-16 23:31:31 · 214 阅读 · 0 评论 -
Item2:尽量以const,enum,inline替换#define
可以改为“宁可以编译器替换预处理器”#define ASPECT_RATIO 1.653ASPECT_RATIO也许从来未被编译器看见,也许在编译器开始处理源码之前就被预处理器移走了。因此,可能没进入记号表(symbol table)内。在运用此常量但获得一个 编译错误信息时,提示1.653而不是ASPECT_RATIO,这就带来一些困惑。解决方案:const double AspectRatio = 1.653;语言常量肯定会被编译器看到,会进入记号表内。可能比使用宏定义导致较小量原创 2020-07-15 00:05:08 · 135 阅读 · 0 评论 -
Item1 视C++为语言联邦
一开始,C++只是C加上一些面向对象的特性。如今,C++是多重范型编程语言。同时支持过程形式(procedural),面向对象形式(object-oriented),函数形式(functional),泛型形式(generic),元编程形式(metaprogramming)。C++是一个由相关语言组成的联邦而非单一语言。C++下主要的次语言有:C:区块、语句、预处理、内置数据类型、数组、指针等 Object-Oriented C++:classes(构造函数、析构函数),封装(encapsu原创 2020-07-14 23:35:26 · 164 阅读 · 0 评论