摘要: 为什么用Inline函数?看起来像函数,但是没有函数调用时的压栈出栈的开销。并且,我们知道编译器最优化的机制通常被设计用来浓缩那些“不含函数调用”的代码。所以当你inline了某个函数,编译器就有能力对它执行语境相关最优化。但是并不是所有的函数都变成inline都好。我们知道,inline后,程序的目标代码是会变大的。 如果在一个内存较小的机子上运行,会导致过多的换页行为,降低高速缓存着墨的命中率,以及伴随而来的低效率。换个角度来说,如果inline的本体很小,编译器针对“函数本体”所产出的码可能比调用所产出的码小,那确实很好,会减少目标码的量,提高高速缓存装置的命中率。Inline函数通常一 阅读全文
posted @ 2012-11-15 22:44 loveyakamoz 阅读(624) 评论(0) 推荐(0) 编辑
摘要: 我们先看一个例子:classPoint{public: Point(intx,inty); voidsetX(intnewVal); voidsetY(intnewVal);};structRectData{ Pointulhc; Pointlrhc;};classRectangle{public: Point&upperLeft()const{returnpData->ulhc;} Point&lowerRight()const{returnpData->lrhc;} ...private: std::tr1::shared_ptr<RectData> 阅读全文
posted @ 2012-11-15 22:43 loveyakamoz 阅读(351) 评论(0) 推荐(0) 编辑
摘要: 只要你定义了一个变量,而类型带有一个构造函数和一个析构函数,你就得忍受构造成本与析构成本。或许你认为你不可能定义一个不会使用的变量,但是请看下面的代码:std::stringencryptPassword(conststd::string&password){ usingnamespacestd; stringencrypted; if(password.length()<MinimumPasswordLength){ throwlogic_error("password is short"); } ... returnencrypted;}对象encrypt 阅读全文
posted @ 2012-11-15 22:42 loveyakamoz 阅读(232) 评论(0) 推荐(0) 编辑
摘要: 首先看看为什么成员变量不该是public的,然后让你看看所有反对public成员变量的论点同样适用于protected成员变量。最后导出一个结论,所有的成员变量都应该是private的。一.语法一致性。如果成员变量不是public的,那么所有的访问成员变量,都变成了函数,所以就不存在是不是有括号的问题了。二.使用成员函数会让你对成员变量有更加精确的控制。因此你可以设计出“不准访问(不写对应此成员的函数)”,“只读访问(const)”,“读写访问”。三.封装。如果你通过函数访问成员变量,日后,当你想用某个计算替换这个成员变量,而class客户一点也不知道class的内部实现已经起了变化。成员变量 阅读全文
posted @ 2012-11-15 22:41 loveyakamoz 阅读(456) 评论(0) 推荐(0) 编辑
摘要: 缺省的情况下,C++是以by value方式传递对象至函数。函数实参都是以实际实参的复件为初始值,而调用端获得的亦是函数返回值的一个复件。这些复件系由对象的copy构造函数产出,这可能使得pass by value成为昂贵的操作。 考虑下面的继承体系:classPerson{public: Person(); vitual~Person();private: std::stringname; std::stringaddress;};classStudent:publicPerson{public: Student(); virtual~Student();private: std::stri 阅读全文
posted @ 2012-11-15 22:40 loveyakamoz 阅读(672) 评论(0) 推荐(0) 编辑
摘要: 上一条款我们说了,能以pass by reference to const 尽量不用pass by value。是不是所有的都要这样呢?这会使我们犯错:开始传递一些reference指向其实并不存在的对象,这不是一件好事。考虑一个用以表现有理数的class,内含一个函数用来计算两个有理数的乘积。classRational{public: Rational(intnumerator=0 intdenominator=-1); ...private: intn,d; friendRationaloperator*(constRational&lhs,constRational&rh 阅读全文
posted @ 2012-11-15 22:40 loveyakamoz 阅读(204) 评论(0) 推荐(0) 编辑
摘要: 当你定义了一个新的class时,也就定义了一个新的type。身为c++程序员,你有许多时间主要用来扩张你的类型系统。这意味着你并不只是class设计者,还是type设计者。重载函数和操作符,控制内存的分配和归还,定义对象的初始化和终结…全都在你的手上。因此你应该带着和“语言设计者当初设计语言内置类型时”一样的谨慎来研讨class的设计。几乎每一个class都要求你面对以下提问。新type的对象应该如何被创建和销毁?对象的初始化和对象的赋值该有什么样的差别?(对应不同的函数)新type的对象如果被pass by value,意味着什么?什么是新type的合法值?对于于class成员变量来说,通常 阅读全文
posted @ 2012-11-15 22:37 loveyakamoz 阅读(251) 评论(0) 推荐(0) 编辑
摘要: 以下动作会有什么错?std::string*stringArray=newstd::string[10];...deletestringArray;这样会导致不明确的错误,因为你申请了一个字符串数组,长度是10,而你只delete了一个,其他的元素的析构函数可能没有调用。当你使用new时,会发生两件事:1)内存被分配出来2)针对此内存会有一个(或更多)构造函数被调用当你使用delete时,也有两件事:1)针对此内存会有一个(或更多)析构函数被调用2)内存才被释放Delete的最大问题在于:即将被删除的内存之内究竟存有多少对象?这个问题的答案决定了有多少个析构函数必须被调用起来。实际上这个问题还 阅读全文
posted @ 2012-11-15 22:36 loveyakamoz 阅读(263) 评论(0) 推荐(0) 编辑
摘要: 所谓有资源,就是你一旦使用了它,就要记得归还系统。如果不这样做,就会发生资源的浪费。这里的资源不仅仅是指内存,也包括:文件描述符,互斥锁,数据库连接…本条款是一个直接而易懂的基于对象的资源管理方法,建立在C++对构造函数,析构函数,copy函数的基础上。经验显示,经过训练后严守这些做法,可以几乎消除资源管理的问题。下面我们就开始了~~~~~首先,我们以工厂模式来说起:假如我们使用一个用来模拟投资行为的程序库,其中各式各样的投资类型继承自一个root class Investment;classInvestment{};进一步假设,这个程序库是通过一个工厂函数供应我们某特定的Investment 阅读全文
posted @ 2012-11-15 22:33 loveyakamoz 阅读(373) 评论(0) 推荐(0) 编辑
摘要: 设计良好的OO系统会将对象的内部封装起来,只留两个函数负责对象拷贝,那便是copy构造函数和copy assignment操作符。 我们知道,如果不给类提供一个copy函数,则当需要时,编译器会为我们提供copy函数。 但是,如果你自己声明了copy函数,就是在拒绝了编译器为你提供的版本。意思是你不喜欢编译器所提供的版本,此时,如果它好像是被冒犯了一样,如果你的代码出现了错误,它也不提醒你。classCustomer{... Customer(constCustomer&rhs); Customer&operator=(constCustomer&rhs);...pri 阅读全文
posted @ 2012-11-15 22:32 loveyakamoz 阅读(341) 评论(0) 推荐(0) 编辑
摘要: 自我赋值发生在对象被赋值给自己:class Widget {...}Widget w ;…w = w // 赋值给自己还有一个隐含的会发生自我赋值的例子: a[i] = a[j];//当i = j时下面有这样一个类:class Bitmap{};class Widget { ...private : Bitmap *pb;};l 版本一Widget& Widget::operator= (const Widget& rhs){ delete pb; pb = new Bitmap(*rhs.pb); return *this;}注意:这里存在一个问题,那就是如果rhs所指的对象 阅读全文
posted @ 2012-11-15 22:31 loveyakamoz 阅读(220) 评论(0) 推荐(0) 编辑
摘要: 关于赋值,我们知道可以连续的进行赋值如: int x, y, z; x = y = z = 12;为了实现连锁的赋值,赋值操作符必须返回一个reference指向操作符的左侧实参,这是你要为class实现赋值操作符时,应该遵循的协议:class Widget {public : ... Widget& operator= (const Widget& rhs){ ... return *this; }}这个协议不仅适用于以上的标准赋值形式,也适用于所有的赋值相关运算,例如:class Widget {public : ... Widget& operator= (con 阅读全文
posted @ 2012-11-15 22:30 loveyakamoz 阅读(240) 评论(0) 推荐(0) 编辑
摘要: 看下面一个类:class TimeKeeper{public : TimeKeeper(); ~TimeKeeper(); ....};class AtomicClock : public TimeKeeper{...};class WaterClock : public TimeKeeper{...};class WristClock : public TimeKeeper{...}; 当我们使用时,我们可以采用一个工厂方法,用基类的指针指向派生类的对象: TimeKeeper * getTimeKeeper();TimeKeeper * ptk = getTimeKeeper(); //用 阅读全文
posted @ 2012-11-15 22:29 loveyakamoz 阅读(272) 评论(0) 推荐(0) 编辑
摘要: 如果你是一个地产商,一个中介软件系统自然而然的想有一个class来描述一个房屋。Class HomeForSale{…};每一个地产商,都会说自己的房子是独一无二的,所以不允许别人复制或赋值。也就是说: HomeForSale h1; HomeForSale h2; HomeForSale h3(h1); // 企图拷贝h1,不应该通过编译 H1 = h2; //企图赋值h1,不应该通过编译这时我们要如何去做呢? 如果我们不定义copy 构造函数或赋值构造函数,则编译器会为我们生成。那么这时我们要怎么办呢? 有一个办法,我们把copy 构造函数或赋值构造函数定义为私有的。 但是问题来了,虽然为 阅读全文
posted @ 2012-11-15 22:28 loveyakamoz 阅读(187) 评论(0) 推荐(0) 编辑
摘要: 读取未初始化的值会造成不明确的行为。对于内置类型来说,我们必须手工完成初始化。对于类类型来说,这个责任由构造函数来承担,所以构造函数要确保所有的数据成员有被初始化。例如下面这个构造函数:ABEntity::ABEntity(const std::string& name, const std::string& address, const std::list<PhoneNumber>& phones) { theName = name; theAddress = address; thePhones = phones; }注意这是我们新手比较容易犯的一个错误 阅读全文
posted @ 2012-11-15 22:27 loveyakamoz 阅读(229) 评论(0) 推荐(0) 编辑
摘要: 什么时候一个空类,不再是空类了呢?当c++编译器处理之后。如果没有定义,编译器会为你产生四个函数:1) 默认构造函数2) Copy构造函数3) 赋值构造函数4) 析构函数注意这些函数都是public且是inline的。这里还有一点要说明的:不是说编译器一定会为你产生这些函数,而是说,当这些函数被调用时,它们才会被编译器创建出来。下面主要谈一谈赋值构造函数:举一个例子: template<class T>class NamedObject{ public: NamedObject(std::string& name, const T& value); ... priv 阅读全文
posted @ 2012-11-15 22:27 loveyakamoz 阅读(281) 评论(0) 推荐(0) 编辑
摘要: 我们经常用define做什么?1) 定义一个常量2) 定义一个宏为什么说尽量不用define。那么以这两个方面来解释:1) 当我们定义一个常量时,我们可以用以下方式:#define ASPECT_PATIO 1.653我们知道编译器并没有看到ASPECT_PATIO符号(为什么?复习程序的预编译,编译,链接,运行)。于是这个记号ASPECT_PATIO并没有进行编译器的记号表内。恰巧如果我们获得了一个编译时期的错误,这个错误信息中会提到1.653而不是ASPECT_PATIO。这时,你会感到不解。如果这个符号ASPECT_PATIO并没有定义在此文件内,则你就可能一头雾水。引起这两种情况的原因 阅读全文
posted @ 2012-11-15 22:26 loveyakamoz 阅读(585) 评论(0) 推荐(0) 编辑