普通成员函数,静态成员函数,及静态成员变量皆不会在类的对象中有所表示,成员函数和对象的关联由编译器在编译时处理,正如我们会在后面看到的那样,编译器会在编译时决议出正确的普通成员函数地址,并将对象的地址以this指针的方式,做为第一个参数传递给普通成员函数,以此来进行关联。静态成员函数类似于全局函数,不和具体的对象关联。静态成员变量也一样。静态成员函数和静态成员变量和普通的全局函数及全局变量不同之处在于它们多了一层名字限定。 三种内存对象的比较 栈对象的优势是在适当的时候自动生成,又在适当的时候自动销毁,不需要程序员操心;而且栈对象的创建速度一般较堆对象快,因为分配堆对象时,会调用operator new操作,operator new会采用某种内存空间搜索算法,而该搜索过程可能是很费时间的,产生栈对象则没有这么麻烦,它仅仅需要移动栈顶指针就可以了。但是要注意的是,通常栈空间容量比较小,一般是1MB~2MB,所以体积比较大的对象不适合在栈中分配。特别要注意递归函数中最好不要使用栈对象,因为随着递归调用深度的增加,所需的栈空间也会线性增加,当所需栈空间不够时,便会导致栈溢出,这样就会产生运行时错误。 堆对象,其产生时刻和销毁时刻都要程序员精确定义,也就是说,程序员对堆对象的生命具有完全的控制权。我们常常需要这样的对象,比如,我们需要创建一个对象,能够被多个函数所访问,但是又不想使其成为全局的,那么这个时候创建一个堆对象无疑是良好的选择,然后在各个函数之间传递这个堆对象的指针,便可以实现对该对象的共享。另外,相比于栈空间,堆的容量要大得多。实际上,当物理内存不够时,如果这时还需要生成新的堆对象,通常不会产生运行时错误,而是系统会使用虚拟内存来扩展实际的物理内存。 接下来看看static对象。 首先是全局对象。全局对象为类间通信和函数间通信提供了一种最简单的方式,虽然这种方式并不优雅。一般而言,在完全的面向对象语言中,是不存在全局对象的,比如C#,因为全局对象意味着不安全和高耦合,在程序中过多地使用全局对象将大大降低程序的健壮性、稳定性、可维护性和可复用性。C++也完全可以剔除全局对象,但是最终没有,我想原因之一是为了兼容C。 其次是类的静态成员,上面已经提到,基类及其派生类的所有对象都共享这个静态成员对象,所以当需要在这些class之间或这些class objects之间进行数据共享或通信时,这样的静态成员无疑是很好的选择。 接着是静态局部对象,主要可用于保存该对象所在函数被屡次调用期间的中间状态,其中一个最显著的例子就是递归函数,我们都知道递归函数是自己调用自己的函数,如果在递归函数中定义一个nonstatic局部对象,那么当递归次数相当大时,所产生的开销也是巨大的。这是因为nonstatic局部对象是栈对象,每递归调用一次,就会产生一个这样的对象,每返回一次,就会释放这个对象,而且,这样的对象只局限于当前调用层,对于更深入的嵌套层和更浅露的外层,都是不可见的。每个层都有自己的局部对象和参数。 在递归函数设计中,可以使用static对象替代nonstatic局部对象(即栈对象),这不仅可以减少每次递归调用和返回时产生和释放nonstatic对象的开销,而且static对象还可以保存递归调用的中间状态,并且可为各个调用层所访问。 不产生堆对象的方法:怎样禁止产生堆对象了?我们已经知道,产生堆对象的唯一方法是使用new操作,如果我们禁止使用new不就行了么。再进一步,new操作执行时会调用operator new,而operator new是可以重载的。方法有了,就是使new operator 为private,为了对称,最好将operator delete也重载为private。现在,你也许又有疑问了,难道创建栈对象不需要调用new吗?是的,不需要,因为创建栈对象不需要搜索内存,而是直接调整堆栈指针,将对象压栈,而operator new的主要任务是搜索合适的堆内存,为堆对象分配空间。好,让我们看看下面的示例代码: #include <stdlib.h> //需要用到C式内存分配函数 class Resource ; //代表需要被封装的资源类 class NoHashObject { private: Resource* ptr ;//指向被封装的资源 … … //其它数据成员 void* operator new(size_t size) //非严格实现,仅作示意之用 { return malloc(size) ; } void operator delete(void* pp) //非严格实现,仅作示意之用 { free(pp) ;… Continue reading 一些关于C++内存布局的知识
Author: Lu Jun
80后男,就职于软件行业。习于F*** GFW。人生48%时间陪同电子设备和互联网,美剧迷,高清视频狂热者,游戏菜鸟,长期谷粉,临时果粉,略知摄影。
Java中字符串的比较
String ta = “ab
C语言测试:想成为嵌入式程序员应知道的0x10个基本问题
C语言测试是招聘嵌入式系统程序员过程中必须而且有效的方法。这些年,我既参加也组织了许多这种测试,在这过程中我意识到这些测试能为带面试者和被面试者提供许多有用信息,此外,撇开面试的压力不谈,这种测试也是相当有趣的。 从被面试者的角度来讲,你能了解许多关于出题者或监考者的情况。这个测试只是出题者为显示其对ANSI标准细节的知识而不是技术技巧而设计吗?这个愚蠢的问题吗?如要你答出某个字符的ASCII值。这些问题着重考察你的系统调用和内存分配策略方面的能力吗?这标志着出题者也许花时间在微机上而不上在嵌入式系统上。如果上述任何问题的答案是”是”的话,那么我知道我得认真考虑我是否应该去做这份工作。 从面试者的角度来讲,一个测试也许能从多方面揭示应试者的素质:最基本的,你能了解应试者C语言的水平。不管怎么样,看一下这人如何回答他不会的问题也是满有趣。应试者是以好的直觉做出明智的选择,还是只是瞎蒙呢?当应试者在某个问题上卡住时是找借口呢,还是表现出对问题的真正的好奇心,把这看成学习的机会呢?我发现这些信息与他们的测试成绩一样有用。 有了这些想法,我决定出一些真正针对嵌入式系统的考题,希望这些令人头痛的考题能给正在找工作的人一点帮住。这些问题都是我这些年实际碰到的。其中有些题很难,但它们应该都能给你一点启迪。 这个测试适于不同水平的应试者,大多数初级水平的应试者的成绩会很差,经验丰富的程序员应该有很好的成绩。为了让你能自己决定某些问题的偏好,每个问题没有分配分数,如果选择这些考题为你所用,请自行按你的意思分配分数。预处理器(Preprocessor) 1 . 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 我在这想看到几件事情: ; #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等) ; 懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。 ; 意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。 ; 如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要。 2 . 写一个”标准”宏MIN ,这个宏输入两个参数并返回较小的一个。 #define MIN(A,B) ((A) <= (B) ? (A) : (B)) 这个测试是为下面的目的而设的: ; 标识#define在宏中应用的基本知识。这是很重要的,因为直到嵌入(inline)操作符变为标准C的一部分,宏是方便产生嵌入代码的唯一方法,对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。 ; 三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比if-then-else更优化的代码,了解这个用法是很重要的。 ; 懂得在宏中小心地把参数用括号括起来 ; 我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事? least = MIN(*p++, b); 3. 预处理器标识#error的目的是什么?… Continue reading C语言测试:想成为嵌入式程序员应知道的0x10个基本问题
UML Tools
以下列出一些常用的UML建模工具Apollo Eclipse 插件, Poseiden(也可以独立运行)Visual Paradigm(Crack not found)Power DesignerMagic DrawIBM Rational Architect
junit测试中的异常情况测试
需要测试一个函数抛出异常时。有两种方法写代码:public void testXXX() { try { testClass.testMethod(param1); } catch (Exception e) { if (e instanceof Exception1) { return; } } fail(); }如上代码中,假设testClass.testMethod会抛出4种类型的异常。我们预测到传入param1给testClass.testMethod时,应该要抛出Exception1的异常。此时,如果没有抛出这个异常而成功执行的话,那么就会走到fail();。如果抛出其他非Exception1的另外3种异常时,也会走到fail();这样的结果另我们非常满意。但是事实上并不完美,原因在于假设抛出了异于我们预计的那10种异常呢?如常见的NullPointerException。此时应该要抛出error,但是这样的写法永远不会有error的情况了。似乎这样写不是最好的方案。 稍微修改一下代码如下:public void testYYYY() { try { … Continue reading junit测试中的异常情况测试
金山词霸2007取词需要DCOM服务
金山词霸的取词功能需要DCOM服务。不然不能取词。并且没有任何提示。
安装Office 2007时的错误
今天在安装Office 2007的时候就不断的出错。弹出的错误信息就是:Microsoft Office Enterprise 2007 encountered an error during setup。没有任何原因。于是打开了系统日志,到%TEMP%目录下找到了安装系统日志文件。找到了最后的一些日志文字说明是windows installer服务没有开启。 在此一记,希望下次不要再花那么多时间来找原因了。
0xc0150004
今天我碰到了启动MSN,QQ等都会出现0xc0150004应用程序初始化失败的问题,搜了一下,找到了解决方案。在此一记。 在C:\WINDOWS\WinSxS中搜索 “8.0.50727.163” 和 “8.0.50727.762”,然后把所有搜索到的结果都删除。
上海人啊
一个德国青年,现在在上海大学找了份交英语的工作一个女孩,他们是恋人还有这个女孩的妈妈德国青年想娶女孩女孩的妈妈不同意德国青年要加入中国国籍他说结婚后想去各处走走,五大名山,敦煌,西双版纳那个妈妈在旁边用上海话说旅游旅游你去旅游好了,你干吗不去旅游要娶我女儿然后主持人问德国青年说结婚后准备住哪儿德国青年说住女孩家这个妈妈用上海话说你凭什么住我家主持人翻成普通话问他结婚后她妈妈不让他们住他家,准备住哪儿德国青年说我们可以租房子,租两室一厅那个妈妈马上说就凭你那点钱,租什么房子,不行,一定要买房子德国青年说买房子,为什么要买房子然后说他可以打工那个妈妈马上说你打工,你去打一辈子工主持人问他你知道为什么她妈妈不同意你们结婚吗他说不太清楚,又问如果她父母不同意,你们会结婚吗德国青年说我当然会和她结婚,我是和她结婚,不是和她妈妈结婚 江苏卫视报道
SQL语句的拼写中需要注意的地方
字符串中的’需要转义为” 如果 like ‘%’ 并不包含null的情况。这点需要注意。