Effective C++
扮猪吃饺子
努力的人,运气不会太差。
展开
-
条款01:视C++为一个语言联邦
C++语言视为一个由相关语言组成的联邦而非单一语言,为了理解C++,要理解其主要的四个次语言:C。说到底C++仍然是以C为基础。区块、语句、预处理、内置类型、数组、指针等统统来自C。 Object-Oriented(面向对象的) C++。这部分也就是C with Classes所诉求:classes,封装、继承、多态、virtual函数等等。 Template C++。这是C++的泛型编程...原创 2019-02-14 15:32:42 · 320 阅读 · 0 评论 -
条款14:在资源管理类中小心copying行为
当你使用RAII来管理资源来的时候,面对对象被复制的时候,会发生什么事情,大多数有如下两种选择:禁止复制。因为对于“同步化基础器物”(synchronization primitives)的副本,如果复制动作对RAII class并不合理,就该禁止。 对底层资源使用“引用计数”。有时候希望保有资源,直达它的最后一个使用者(某对象)被销毁。这种情况下复制RAII对象时,就该将资源的“被引用计数...原创 2019-05-30 06:59:38 · 155 阅读 · 0 评论 -
条款13:以对象管理资源
·所谓资源就是,一旦用了它,将来必须还给系统。C++中最常见的资源就是动态内存分配,其他资源包括文件描述器、互斥锁、图形界面中的字型和笔刷、数据库连接、以及网络sockets。对于手工释放资源,ro为了容易发生某些错误,会资源泄露,我们解决的方法可以把资源放进对象内,依赖C++的析构函数自动调用机制确保资源被释放。许多资源被动态分配于heap内后被用于单一区块或函数内,它们应该再控制流离开...原创 2019-05-29 07:16:11 · 129 阅读 · 0 评论 -
条款17:以独立语句将newed对象置入智能指针
假设某个函数用来揭示程序的优先权,另一个函数用来在某个动态分配所得Widget上进行某些带有优先权的处理,并且“以对象管理资源”,即processWdiget决定对其动态分配而来的Widget运用智能指针:int priority();void processWidget(std::tr1::shared_ptr<Widget> pw,int priority);//调用...原创 2019-05-31 07:22:36 · 177 阅读 · 0 评论 -
条款16:成对使用new和delete要采取相同形式
当你使用new的时候,一是内存被分配(通过operator new函数),然后是构造函数被调用。当你delete的时候,析构函数被调用,然后内存被释放(通过operator delete)。游戏规则:如果你调用new时使用[ ],你必须在对应调用delete时也使用[ ]。如果你调用new时没使用[ ],那么也不该在对应delete时使用[ ]。为了避免诸如此类的错误,最好不要对数组形式做...原创 2019-05-31 06:59:50 · 148 阅读 · 0 评论 -
条款12:复制对象时勿忘其每一个成分
设计良好的面向对象系统(OO-systems)会将对象的内部封装起来,只留两个函数负责对象拷贝(复制),那便是copy构造函数和copy assignment操作符,统称为copying函数。编译器会在必要时候为我们的classes创建copying函数,如果你不喜欢编译器生成的copying,你可以自己声明copying函数,但是当你出错时却不告诉你。1.当你写好copying系列函数的时候...原创 2019-05-28 07:20:30 · 176 阅读 · 0 评论 -
条款11:在operator=中处理“自我赋值”
“自我赋值”发生在对象被赋值给自己时://方式1class Widget{...};Widget w;...w = w;//方式2a[i] = a[j]; //潜在的自我赋值,如果i和j有相同的值//方式3*px = *py; //潜在的自我赋值,若px和py指向同一个东西class Base{...};class Derived: public Base{......原创 2019-05-27 08:01:14 · 299 阅读 · 0 评论 -
条款10:令operator=返回一个reference to *this
关于赋值,C++内置类型可以写成连锁形式,赋值都采用右结合律:int x,y,z;x = y = z = 15; //赋值连锁形式//解析如下形式x = (y = (z = 15)); 为了实现“连锁赋值”,赋值操作符必须返回一个reference指向操作符的左侧实参。class Widget{public: ... Widget& operator = (...原创 2019-05-25 09:19:34 · 175 阅读 · 0 评论 -
条款09:绝不在构造和析构函数中调用virtual函数
重点:对于C++语言来讲,它和java或者C#不同的是你不该在析构函数和析构函数期间调用virtual函数,因为这样调用会带来预想不到的结果,就算有你也不会高兴。对于继承而言,base class构造期间,virtual函数不是virtual函数。在derived class对象的base class构造期间,对象的类型是base class而不是derived calss。不只virtual...原创 2019-05-25 09:07:54 · 205 阅读 · 0 评论 -
条款06:若不想使用编译器自动生成的函数,就该明确拒绝
对于一个class而言,如果你不希望支持某个特定机能,只要不声明对应函数就是了,但是这个策略对于C++编译器会默默给你生成的函数(default构造函数、析构函数、copy构造函数和copy assignment操作符)而言却不起作用,如果你不声明它们,而某些人尝试调用,编译器就会为你声明它们。如果你要阻止这些行为:因为编译器产出的函数都是public,为了阻住它们,你可以将其声明为priva...原创 2019-05-16 07:38:07 · 133 阅读 · 0 评论 -
条款05:了解C++默默编写并调用了哪些函数
对于一个empty class(空类),编译器就会为它声明(编译器版本的)一个copy构造函数,一个copy assignment操作符和一个析构函数,此外你没有声明任何构造函数,编译器也会为你声明一个default构造函数。如下所示://当你写下如下的代码:class Empty{};//就像如下的代码一样:class Empty{public: Empty{...}; ...原创 2019-05-16 07:09:07 · 149 阅读 · 0 评论 -
条款08:别让异常逃离析构函数
C++并不禁止析构函数吐出异常,但它不鼓励你这样做。如果你的析构函数必须执行一个动作,而该动作可能在失败时抛出 异常,你该如何办呢?如下你使用一个class负责数据库连接://数据库连接类class DBConnection{public: ... static DBConnection create(); //返回DBConnection对象 void close(); ...原创 2019-05-21 07:12:21 · 125 阅读 · 0 评论 -
条款07:为多态基类声明virtual析构函数
C++明确指出:当derived对象经由一个base class指针被删除,而该base class带有一个non-virtual析构函数,其结构未定义的——实际执行时通常发生的是对象的derived成分没被销毁。这种情况下就只有base class成分被销毁,于是造成诡异的“局部销毁”对象,形成资源泄露。消除这种方法做法很简单:给base class一个析构函数,这样做,它会销毁整个对象...原创 2019-05-20 07:23:56 · 111 阅读 · 0 评论 -
条款04:确定对象被使用前已先被初始化
最佳的处理方法:永远在使用对象的之前先将他初始化,对于无任何成员的内置类型,你必须手工完成此时;对于内置类型以外的任何其他东西,初始化责任落在构造函数身上:确保每一个构造函数都将对对象的每一个成员初始化。但是别混淆赋值(assignment)和初始化(initialization)。//内置类型如下int x = 0; //对int进行手工初始化const char* ...原创 2019-05-15 07:20:01 · 191 阅读 · 0 评论 -
条款03:尽可能使用const
关键字const多才多艺。你可以用它在classes外部修饰global或namespace作用域中的常量,或修饰文件、函数或区块作用域中被声明static的对象。你也可以修饰classes内部的static和non-static成员变量。面对指针你也可以指出自身、指针所指物或两者都(或不)是const。char* greeting = "Hello";char* p = greeting...原创 2019-03-29 14:57:51 · 148 阅读 · 0 评论 -
条款02: 尽量以const,enum,inline替换 #define
条款或许改为“宁可以编译器替换预处理”更好,因为或许#define不被视为语言的一部分。对于如下的宏定义以常量替换:#define ASPECT_RATIO 1.653const double AspectRatio = 1.653;原因:ASPECT_RATIO从未被编译器看到;你所使用的名称可能并未进入记号表(symbol table),作为语言常量AspectRatio肯定...原创 2019-02-20 10:16:06 · 230 阅读 · 0 评论 -
条款15:在资源管理类中提供对原始资源的访问
对于资源管理类而言,有时候你需要处理原始资源(raw resources)的访问。当你使用智能指针如auto_ptr或tr1::shared_ptr保存资源类的时候。当你需要访问智能指针指向的原始资源的时候,你有显示转换和隐式转换两个方法:显示使用智能指针的get函数,隐式方法智能指针重载了指针的取值操作符(operator->和operator*)。有时候必须取得RAII对象内的原始资...原创 2019-05-30 07:41:26 · 130 阅读 · 0 评论