
effective c++
文章平均质量分 63
零下的温度
这个作者很懒,什么都没留下…
展开
-
49~52new和delete
文章目录@[toc]一、了解new-handler的行为二、了解new和delete的合理替换时机三、编写new和delete时需固守常规四、写了placement new 也要写placement delete一、了解new-handler的行为set_new_handlernamespace std{ typedef void (*new_handler)(); new_handler set_new_handler(new_handler p) throw();//trhow原创 2022-05-22 16:07:03 · 192 阅读 · 0 评论 -
32~40继承与面向对象设计
一、确定你的public继承塑模出is-a关系piublic inheritance意味着“is-a”的关系。适用于base classes身上 的每一件事情一定也适用于derived classe身上,因为每一个derived classe对象也是一个base classe对象 。现实或数学逻辑上是is-a关系的事务,在程序的世界并不一定是is-a的关系。考虑Penguin(企鹅) 、Bird和Square、Rectangle的例子。二、避免遮掩继承而来的名称全局变量和局部变量的遮掩原创 2022-05-22 08:23:56 · 345 阅读 · 0 评论 -
31 将文件的编译依存关系降至最低
一、class定义式中包含实现细目class Person{public: Person(const std::string& name,const Date&birthday, const Address& addr); std::string name() const; std::string birthDate() const; std::string address() const; ...private: //实现细目原创 2022-05-20 11:31:09 · 235 阅读 · 0 评论 -
30 透彻了解inlining的里里外外
一、了解inline优点:可以免除函数调用成本编译器有能力对inline函数执行语境相关最优化,编译器最优化机制的设计目的是通常是为了优化“不含函数调用”的代码可能导致较小的目标代码和较高的指令告诉缓存装置击中率缺点:对inline函数的每一个调用都以函数本体替换,会增加目标代码的大小。过多的inline会造成程序体积太大、代码膨胀亦会导致额外的换页行为,降低高速缓存装置的击中率inline只是对编译器的一个申请,不是强制命令二、inline声明方式隐喻方式: 将函数定义于cl原创 2022-05-13 09:50:41 · 246 阅读 · 0 评论 -
28 29 为“异常安全”而努力是值得的
一、异常安全函数提供以下三个保证基本承诺:如果异常被抛出,程序内的任何事务仍然保持在有效状态下。没有任何对象或数据结构会因此而败坏,所有对象都处于一种内部前后一致的状态(例如所有的class约束条件都继续获得满足)。如果含函数出现异常,程序有可能处于任何状态——只要那是个合法状态。强烈保证:如果异常抛出,程序状态不改变。调用这样的函数需要有这样的认知:如果函数成功,就是完全成功,如果函数失败,程序会回复到“调用函数之前”的状态。不抛异常保证:承诺不抛出异常,因为他们总是能够完成他们原先承诺的功能。作原创 2022-05-11 16:34:29 · 241 阅读 · 0 评论 -
27 尽量少做转型动作
一、旧式转型(C风格)(T)expression 强制转型,将expression转型为TT(expression) 函数式转型,将expression转型为T二、新式四种转型(C++风格)const_cast(expression)通常被用来将对象的常量性转除。唯一有此能力的C+±style转型操作符。dynamic_cast(expression)主要用来执行“安全向下转型”,也就是用来决定某对象是否归属继承体系中的某个类型。它是唯一无法用旧式语法执行的动作,也是唯一可能耗费重大原创 2022-05-10 20:20:57 · 242 阅读 · 0 评论 -
26 尽可能延后变量定义式的出现时间
一、现象情况1:过早定义变量会导致变量存在未被完全使用的情况,增加构造析构的成本。std::string encryptPassword( const std::string& password ){ using namespace std; string encrypted; if(password.length() < MinimumPasswordLength){ throw logic_error("Password is too sho原创 2022-05-10 17:47:16 · 185 阅读 · 0 评论 -
25 考虑写出一个不抛异常的swap
一、std::swapstd::swap面对指针(如pImpl写法)时效率低,因此需要重写swap1.1 如何重写swap为标准库提供特化版本(全特化)//pImpl写法的Widgetclass WidgetImpl{public: ... void swap(Widget& other){ using std::swap; swap(pImpl,other.pImpl); }private: int a,b,c;原创 2022-05-09 21:46:23 · 386 阅读 · 0 评论 -
20 21参数传递及返回值和引用关系
20 宁以pass-by-reference-to-const替换pass-bu-value一、原因按值传递会创建对象副本,多次调用构造和析构,效率低。按引用传递不会创建对象,效率高。按引用传递可以避免对象切割问题。derived class对象按值传递,并被视为一个base class对象,base class的copy构造函数会被调用,derived class对象的行为会被丢掉。二、内置类型在编译器底层,references往往以指针实现出来。 pass by reference 通常原创 2022-05-09 20:17:31 · 196 阅读 · 0 评论 -
23 24 什么时候用non-member函数替代member函数
23 宁以 non-member、non-friend 替换member函数,可增加封装性、包裹弹性和机能扩充性non-member non-friend 函数相对于member和friend函数而言,具有更大的封装性,因为它不能够访问class内之private成分。non-member 可以是另一个class 的member,如工具类。C++中比较自然的做法是让non-member成为与class同一命名空间中的non-member函数,常称为便利函数。当某个class拥有大量的便利函数时,可原创 2022-05-09 20:06:28 · 594 阅读 · 0 评论 -
19 设计class犹如设计type
■ **新type的对象应该如何被创建和销毁?**这会影响到你的class的构造函数和析构函数以及内存分配函数和释放函数(operator new,operator new[],operator delete和operator delete[])的设计,当然前提是如果你打算撰写它们。■ **对象的初始化和对象的赋值该有什么样的差别?**这个答案决定你的构造函数和赋值(assignment)操作符的行为,以及其间的差异。很重要的是别混淆了“初始化”和“赋值”,因为它们对应于不同的函数调用。■ **新typ原创 2022-05-03 16:33:19 · 260 阅读 · 0 评论 -
18 让接口容易被正确使用,不易被误用
一、通过导入新类型来预防错误struct Day{ explict Day(int d) : val(d){} int val;}struct Month{ explict Month(int d) : val(d){} int val;}struct Year{ explict Year(int d) : val(d){} int val;}class Date{public://Date(int m,int d原创 2022-05-02 22:41:13 · 275 阅读 · 0 评论 -
13 14 15 16 17对象管理资源
13 以对象管理资源一、对象管理资源(智能指针)获得资源后立刻放进管理对象内以对象管理资源的观念常被称为“资源取得的时机便是初始化时机(Resource Acquistion Is Initialization;RAII)”管理函数运用析构确保资源被释放。14 在资源管理类中小心copying行为并非所有的资源都是heap-based,如Mutex,需要lock和unlock操作。此时你需要编写自己的资源管理类。需要注意copying 函数的行为。当你自己编写的资源管理类发生复制时,泥坑原创 2022-05-01 23:49:21 · 194 阅读 · 0 评论 -
12 复制对象时勿忘其每一个成分
一、当增加新的成员变量时如果你为class添加一个新的成员变量,你必须同时修改copying函数。也需要修改class所有的构造函数以及任何非标准形式的operator=。此种情况编译器不会报错。二、当发生继承时为derived class撰写copying函数时,必须使用base class的copying函数复制其base class成分。因为base class中往往包含private的成员变量。三、不要尝试用一个copying函数实现另一个copying函数用copy assignmen原创 2022-05-01 22:24:30 · 245 阅读 · 0 评论 -
11 在operator中处理自我赋值
这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入欢迎使用Markdown编辑器你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Mar原创 2022-05-01 21:44:07 · 206 阅读 · 0 评论 -
9 绝不再构造和析构中调用virtual函数 10 operator=
一、为什么不要在构造和析构中调用virtual函数构造中调用virtual函数,virtual函数不会下降到derived classes。原因:1)base class构造函的执行早于derived class构造函数,当base class构造函数执行时derived class的成员变量尚未初始化。而derived class的成员函数几乎必定会调用local成员变量,这会导致未定义行为,因此c++禁止;2)derived class对象的base class构造期间,对象的类型是base原创 2022-04-30 23:26:57 · 942 阅读 · 0 评论 -
8 别让异常逃离析构函数
一、为什么析构函数中不能要吐出异常析构函数中有异常会导致资源泄露。如:析构函数中有异常发生,可能会导致异常后的资源得不到释放。更为严重的是如果vector中包含10个对象,析构第一个元素的时候抛出了异常,但是其他的对象还是应该被销毁,析构第二个元素的时候又抛出了异常。在两个异常同时存在的情况下,程序若不是结束执行就是导致不明行为。二、如果析构函数必须执行会抛出异常的动作,该如何处理如果析构函数必须执行抛出异常的动作,有两种方案解决:1)捕获异常,终止程序(使用abort);2)捕获异常,吐下它原创 2022-04-30 22:56:30 · 258 阅读 · 0 评论 -
07 为多态基类声明虚析构函数
一、多态基类为什么要声明虚析构函数当derived class对象经由一个base class指针被删除,而该bass class 带着一个non-virtual吸狗善书,其结果未有定义——实际执行时通常发生的是对象的的derived成分没有被销毁。二、为什么多态基类中声明为虚析构函数,派生类就会被析构?析构函数的运作方式:最深层派生的那个class其析构函数最先被调用,然后是其每一个base class的析构函数被调用。(运作方式如何实现的?见下段粗体字。 )抽象类的析构函数声明为纯虚析构函数:原创 2022-04-30 22:33:47 · 309 阅读 · 0 评论 -
5 c++默认编写了哪些函数
一、c++默认编写了哪些函数copy构造函数、一个copy assignment操作符和一个析构函数、default构造函数。当这些函数被需要时,它们才会被编译器创建出来。注意:编译器产出的析构函数是个non-virtual,除非这个class的base class自身声明有virtual析构函数(这种情况下这个函数的虚属性virtualness主要来自base class.)。二、这些函数做了哪些操作copy构造函数和copy assignment操作符:将来源对象的每一个non-static原创 2022-04-30 21:34:33 · 1045 阅读 · 0 评论 -
确定对象使用前已先被初始化
1.初始化规则如果使用C part of C++而且初始化可能招致运行期成本,那么就不保证发生初始化。non-C parts of C++,规则有些变化。这就很好地解释了为什么array(来自C part of C++)不保证其内容被初始化,而vector(来自STL part of C++)却有此保证2. 使用初始化列表区分赋值和初始化C++规定,对象的成员变量的初始化动作发生在进入构造函数本体之前。初始化列表中的是初始化,构造函数中的是赋值,赋值之前会先调用default构造函数进原创 2022-04-24 21:26:35 · 891 阅读 · 0 评论 -
尽可能使用const
const 出现在*左边,表示被指物是常量,出现在*右边,表示指针自身是常量。迭代器中的const:1)const_iterator的作用为:const T* 和T const *2)const std::vector<int>::iterator iter;等同于:T* constconst修饰返回值的作用是防止返回值被错误的赋值,如:class Rational{...};const Rational operator*(const Rational& ...原创 2022-04-24 13:15:46 · 216 阅读 · 0 评论