随笔分类 -  C/C++

摘要:一个堆可以被看作一棵二叉树和一个数组。堆排序主要分为以下几步:建堆,取出堆顶元素,调整堆,递归处理。本文中给出了在数组上建堆和调整以及堆排序的相关代码实现和实现过程的图示,以供参考。 阅读全文
posted @ 2014-05-27 11:00 suzhou 阅读(1383) 评论(2) 推荐(0) 编辑
摘要:本文主要参考《Effective C++ 3rd》中的第六章部分章节的内容。 关注的问题集中在继承、派生、virtual函数等。如: virtual? non-virtual? pure virtual? 缺省参数值与virtual函数有什么交互影响? 继承如何影响C++的名称查找规则? 什么情况下有比virtual更好的选择? 阅读全文
posted @ 2014-05-19 15:57 suzhou 阅读(1092) 评论(2) 推荐(0) 编辑
摘要:主要探讨对象、继承、多态在内存中的表现形式。 阅读全文
posted @ 2014-04-11 13:22 suzhou 阅读(2177) 评论(0) 推荐(2) 编辑
摘要:问题聚焦: 这一节不涉及代码,但是我们需要明确的一点是,思想比代码要重要得多。 设计优秀的classes是一项艰巨的工作,就像设计好的types一样。 我们应该带着和“语言设计者当初设计语言内置类型时”一样的谨慎来研讨class的设计。那么,如何设计高效的classes呢?下面几乎每一个针对class设计的提问,往往就是你所需要遵守的设计规范。1 新type的对象应该如何被创建和销毁? 这会影响到你的class的构造函数和析构函数以及内存分配函数和释放函数的设计。2 对象的初始化和对象的赋值该有什么样的差别? 这个答案决定你的构造函数和赋值操作符的行为,以及其间的差异。 很重要的一... 阅读全文
posted @ 2014-02-11 09:44 suzhou 阅读(303) 评论(0) 推荐(0) 编辑
摘要:问题聚焦: 从这个条款开始,我们把注意力转移到软件设计和声明上来,具体的说就是,C++接口的设计和声明。 所谓软件设计,就是以一般习惯的构想开始,演变成细节的实现,最终开发针对性的特殊接口。 接口的设计和声明的一个最基本的准则是:让接口容易被正确使用,不容易被误用。 引入新类型是预防接口被误用的常见手段之一。欲开发一个好的接口,首先必须考虑客户可能做出什么样的错误。来看下面这个例子class Date{public: Date(int month, int day, int year); ... ...};上面这个接口有什么问题呢?(如果你觉得没问题的话,那么就该像我一样老... 阅读全文
posted @ 2014-02-11 09:14 suzhou 阅读(251) 评论(0) 推荐(0) 编辑
摘要:问题聚焦: 使用了资源管理对象(如智能指针),就一定是安全的吗?显然不是。 资源泄露发生可能在于,在“资源被创建”和“资源被转换为资源管理对象”两个时间点之间有可能发生异常干扰。看下面这个例子://函数说明int priority(); //揭示处理程序的优先权void processWidget(std::tr1::shared_ptr pw, int priority); // 用来在某动态分配所得的Widget上进行某些带有优先权的处理 ... 阅读全文
posted @ 2014-02-02 20:17 suzhou 阅读(389) 评论(0) 推荐(0) 编辑
摘要:问题聚焦: 我们都知道,new和delete要成对使用,但是有时候,事情往往不是按我们预期的那样发展。 对于单一对象和对象数组,我们要分开考虑 遇到typedef时,也需要搞清楚,是单一对象类型还是对象数组类型来看一个例子:std::string* stringArray = new std::string[100];...delete stringArray;问题:stringArray所含的100个string对象中的99个可能并没有被适当地删除,因为它们的析构函数很可能没有被调用。我们来了解一下,使用new时发生了什么,一共有两个动作:内存被分配出来针对此内存会有一个或更多个构造函... 阅读全文
posted @ 2014-02-02 19:45 suzhou 阅读(207) 评论(0) 推荐(0) 编辑
摘要:问题聚焦: 资源管理类是为了对抗资源泄露。 如果一些函数需要访问原始资源,资源管理类应该怎么做呢? 关于资源管理的概念总是显得那么的高大上,其实只是抽象一点。下面用一个例子还说明本节的主题:在前面Effective C++(13) 用对象管理资源中我们提到过,使用智能指针保存工厂函数返回的结果std::tr1::shared_ptr pInv(createInvestment());//加入有某个函数,用来处理Investment对象,像下面这样int daysHeld(const Investment* pi); // 返回投资天数//那么像下面这样的调用时错误的int d... 阅读全文
posted @ 2014-02-01 23:30 suzhou 阅读(247) 评论(0) 推荐(0) 编辑
摘要:问题聚焦: 上一条款所告诉我们的智能指针,只适合与在堆中的资源,而并非所有资源都是在堆中的。 这时候,我们可能需要建立自己的资源管理类,那么建立自己的资源管理类时,需要注意什么呢?。在详述这一章的主题之前,先回忆一下上一节所提到的一个名词——RAII(Resource Acquisition Is Initialization)含义就是:资源取得时机便是初始化时机。如果上一节对这个观念的理解还不是很深的话,那么下面这个例子可以让你更好地理解。Demo假设我们使用C API函数处理类型为Mutex的互斥器对象,共有lock和unlock两函数可用。void lock(Mutex* pm);v.. 阅读全文
posted @ 2014-01-23 09:29 suzhou 阅读(214) 评论(0) 推荐(0) 编辑
摘要:问题聚焦:从这条准则开始,都是关于资源管理的。资源,一旦用了它,将来必须还给系统。本条准则,基于对象的资源管理办法,建立在C++的构造函数,析构函数和拷贝函数(拷贝构造函数和重载赋值操作符)的基础上。Demo:root class Investment:class Investment { ... };// 工厂函数Investment* createInvestment(); // 返回指向一个Investment或者其子类的对象,调用者有责任删除它// 考虑如下调用void f() { Investment* pInv = createInvestment(); ........ 阅读全文
posted @ 2014-01-02 09:32 suzhou 阅读(189) 评论(0) 推荐(0) 编辑
摘要:问题聚焦:负责拷贝的两个操作:拷贝构造函数和重载赋值操作符。一句话总结,确保被拷贝对象的所有成员变量都做一份拷贝。Demovoid logCall(const std::string& funcName); // log函数class Date{ ... };class Customer {public: .... Customer(const Customer& rhs); Customer& operator=(const Customer& rhs);private: std::string name; Date lastTransaction;};Cus 阅读全文
posted @ 2013-12-31 09:29 suzhou 阅读(249) 评论(0) 推荐(0) 编辑
摘要:问题聚焦:自我赋值看似有点愚蠢的行为,其实总会发生的首先:它是合法的,其次,它不一定是安全的,再次,它有时候不是那么明显。先看一个Democlass Widget { ... };Widget w;... /** 最明显的自我赋值 **/w = w; /** 不那么明显的自我赋值 **/// 在某个地方实现了i = j或者相同作用的事情a[i] = a[j]/** 潜在的自我赋值 **/*px = *py;/** 更为隐蔽的自我赋值“别名” **/class Base { ... };class Derived : public Base { ... };void doSomething(.. 阅读全文
posted @ 2013-12-30 20:07 suzhou 阅读(352) 评论(0) 推荐(0) 编辑
摘要:问题聚焦:这个准则比较简短,但是往往就是这种细节的地方,可以提高你的代码质量。细节决定成败,让我们一起学习这条重载赋值操作符时需要遵守的准则吧。还是以一个例子开始:Demo// 连锁赋值x = y = z = 15;// 上面的表达式等价于x = ( y = ( z = 15 ) );为了实现上述的... 阅读全文
posted @ 2013-12-30 18:38 suzhou 阅读(278) 评论(0) 推荐(0) 编辑
摘要:问题聚焦:不要在构造函数和析构函数中调用virtual函数,因为这样的调用不会带来你预想的结果。 让我先来看一下在构造函数里调用一个virtual函数会发生什么结果Democlass Transaction {public: Transaction(); virtual void logTransa... 阅读全文
posted @ 2013-12-26 15:34 suzhou 阅读(297) 评论(0) 推荐(0) 编辑
摘要:问题聚焦:已经对一个对象执行了delete语句,还会发生内存泄漏吗?先来看个demo:// 计时器类class TimeKeeper {public: TimeKeeper(); ~TimeKeeper();};class AtomicClock: public TimeKeeper {... 阅读全文
posted @ 2013-12-24 17:09 suzhou 阅读(211) 评论(0) 推荐(0) 编辑
摘要:问题聚焦:如果不希望class支持某一成员函数,那么不声明和定义它就可以了,但是这一策略对与拷贝构造函数和重载赋值操作符并不起作用。因为如果不声明它们,那么当尝试调用它们的时候,编译器会为你声明和定义它们。这显然不是你所希望看到的。方法:将这类你不想使用并且也不想编译器为你声明的函数声明为priva... 阅读全文
posted @ 2013-12-24 15:23 suzhou 阅读(223) 评论(0) 推荐(0) 编辑
摘要:危害:读取未初始化的值会导致不明确甚至是半随机化的行为。最佳处理办法:永远在使用对象之前先将它初始化;确保每一个构造函数都将对象的每一个成员初始化。1 注意区分赋值和初始化:从初始化的角度而言,这不是一个最佳的处理办法。虽然这会让对象的指最终为你期望的值,但是实际上,对象的成员变量的初始化动作发生在... 阅读全文
posted @ 2013-12-24 14:51 suzhou 阅读(250) 评论(0) 推荐(0) 编辑
摘要:预热:一个空的类,当编译器处理过之后,就包含:一个copy构造函数一个重载赋值操作符一个析构函数一个默认构造函数Demo:class Empty() { }; // 声明一个空的类class Empty() // 经过编译器处理后{public: Empty() { ... 阅读全文
posted @ 2013-12-23 11:45 suzhou 阅读(225) 评论(0) 推荐(0) 编辑
摘要:1 C++最主要的四部分:CObject-Oriented C++: 面向对象Template C++:泛型编程STLC++高效编程守则视状况而变化,取决于你使用C++的哪一部分。2 尽量以const, enum , inline替换 #define2.1#define ASPECT_RATIO ... 阅读全文
posted @ 2013-12-23 11:06 suzhou 阅读(336) 评论(0) 推荐(0) 编辑