摘要:
为什么用Inline函数?看起来像函数,但是没有函数调用时的压栈出栈的开销。并且,我们知道编译器最优化的机制通常被设计用来浓缩那些“不含函数调用”的代码。所以当你inline了某个函数,编译器就有能力对它执行语境相关最优化。但是并不是所有的函数都变成inline都好。我们知道,inline后,程序的目标代码是会变大的。 如果在一个内存较小的机子上运行,会导致过多的换页行为,降低高速缓存着墨的命中率,以及伴随而来的低效率。换个角度来说,如果inline的本体很小,编译器针对“函数本体”所产出的码可能比调用所产出的码小,那确实很好,会减少目标码的量,提高高速缓存装置的命中率。Inline函数通常一 阅读全文
摘要:
我们先看一个例子: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> 阅读全文
摘要:
只要你定义了一个变量,而类型带有一个构造函数和一个析构函数,你就得忍受构造成本与析构成本。或许你认为你不可能定义一个不会使用的变量,但是请看下面的代码:std::stringencryptPassword(conststd::string&password){ usingnamespacestd; stringencrypted; if(password.length()<MinimumPasswordLength){ throwlogic_error("password is short"); } ... returnencrypted;}对象encrypt 阅读全文
摘要:
首先看看为什么成员变量不该是public的,然后让你看看所有反对public成员变量的论点同样适用于protected成员变量。最后导出一个结论,所有的成员变量都应该是private的。一.语法一致性。如果成员变量不是public的,那么所有的访问成员变量,都变成了函数,所以就不存在是不是有括号的问题了。二.使用成员函数会让你对成员变量有更加精确的控制。因此你可以设计出“不准访问(不写对应此成员的函数)”,“只读访问(const)”,“读写访问”。三.封装。如果你通过函数访问成员变量,日后,当你想用某个计算替换这个成员变量,而class客户一点也不知道class的内部实现已经起了变化。成员变量 阅读全文
摘要:
缺省的情况下,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 阅读全文
摘要:
上一条款我们说了,能以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 阅读全文
摘要:
当你定义了一个新的class时,也就定义了一个新的type。身为c++程序员,你有许多时间主要用来扩张你的类型系统。这意味着你并不只是class设计者,还是type设计者。重载函数和操作符,控制内存的分配和归还,定义对象的初始化和终结…全都在你的手上。因此你应该带着和“语言设计者当初设计语言内置类型时”一样的谨慎来研讨class的设计。几乎每一个class都要求你面对以下提问。新type的对象应该如何被创建和销毁?对象的初始化和对象的赋值该有什么样的差别?(对应不同的函数)新type的对象如果被pass by value,意味着什么?什么是新type的合法值?对于于class成员变量来说,通常 阅读全文
摘要:
以下动作会有什么错?std::string*stringArray=newstd::string[10];...deletestringArray;这样会导致不明确的错误,因为你申请了一个字符串数组,长度是10,而你只delete了一个,其他的元素的析构函数可能没有调用。当你使用new时,会发生两件事:1)内存被分配出来2)针对此内存会有一个(或更多)构造函数被调用当你使用delete时,也有两件事:1)针对此内存会有一个(或更多)析构函数被调用2)内存才被释放Delete的最大问题在于:即将被删除的内存之内究竟存有多少对象?这个问题的答案决定了有多少个析构函数必须被调用起来。实际上这个问题还 阅读全文
摘要:
所谓有资源,就是你一旦使用了它,就要记得归还系统。如果不这样做,就会发生资源的浪费。这里的资源不仅仅是指内存,也包括:文件描述符,互斥锁,数据库连接…本条款是一个直接而易懂的基于对象的资源管理方法,建立在C++对构造函数,析构函数,copy函数的基础上。经验显示,经过训练后严守这些做法,可以几乎消除资源管理的问题。下面我们就开始了~~~~~首先,我们以工厂模式来说起:假如我们使用一个用来模拟投资行为的程序库,其中各式各样的投资类型继承自一个root class Investment;classInvestment{};进一步假设,这个程序库是通过一个工厂函数供应我们某特定的Investment 阅读全文
摘要:
设计良好的OO系统会将对象的内部封装起来,只留两个函数负责对象拷贝,那便是copy构造函数和copy assignment操作符。 我们知道,如果不给类提供一个copy函数,则当需要时,编译器会为我们提供copy函数。 但是,如果你自己声明了copy函数,就是在拒绝了编译器为你提供的版本。意思是你不喜欢编译器所提供的版本,此时,如果它好像是被冒犯了一样,如果你的代码出现了错误,它也不提醒你。classCustomer{... Customer(constCustomer&rhs); Customer&operator=(constCustomer&rhs);...pri 阅读全文