随笔 - 576  文章 - 0  评论 - 62  阅读 - 219万
02 2014 档案
理解extern
摘要:extern有两层含义:表示声明和extern C1、C++分为编译期和运行期,C++是分别单独编译,编译期可认为有三个步骤:a、预编译进行文本替换,将源文件(cpp文件)生成编译单元;b、编译单元经过编译生成目标文件(obj文件);c、所有目标文件连接生成库(dll文件)或者可执行文件(exe文件)。2、在每个编译单元中,要使用一个对象,有两种方式: a、在当前把它定义出来 b、告诉编译器,我有这个东西,但是它被定义在其他的编译单元,等到连接时找到它。这就是extern的第一个用法。3、extern修饰对象,说明只是声明,对象定义在其他地方,连接的时候找到他。可以编译通过,但是,你引用的.. 阅读全文
posted @ 2014-02-28 20:21 Andy Niu 阅读(1575) 评论(0) 推荐(0) 编辑
变量的属性
摘要:1、变量有三个基本要素:类型,名称,值。除了这三个要素,还包括其他内容:存储类型,作用域范围,连接类型(可见性),生存期。2、以方法为例说明,方法的类型就是去掉方法名,包括返回类型和形参表,如void (int)。名称就是方法名,方法名表示方法体代码在内存中的地址,在编译时就确定其值,因此是一个常量,这就是方法的值。方法的存储类型默认为extern,只是声明。作用域范围就是文件作用域,连接类型为extern,除非声明为static,为内链接。生存期为永久,从程序运行到程序终止。 阅读全文
posted @ 2014-02-28 19:20 Andy Niu 阅读(934) 评论(0) 推荐(0) 编辑
C++ 内存相关
摘要:1、C++的内存管理可分为以下几个部分: 栈:记录程序的执行过程。 堆:采用new,delete申请释放内存。 自由存储区:对应于C中使用malloc,free申请释放内存。 全局存储区:也叫静态存储区,存储static对象,包括全局对象,命名空间内对象,文件作用域内的static对象,类中的static对象,方法内的static对象。 常量存储区:存放文本常量。2、对于32位系统,堆可用大小为为4G,对于一般程序,可认为无限大。栈可用大小为1M,也可以人为修改。3、 1Byte = 8Bit 1Word = 2Byte 1K = 1024Byte 1M = 1024K 1G... 阅读全文
posted @ 2014-02-28 19:12 Andy Niu 阅读(288) 评论(0) 推荐(0) 编辑
理解TCP可靠的通信
摘要:1、TCP通信是可靠的,UDP通信是不可靠的。TCP是怎么保证通信可靠的呢?2、实际项目中,用到串口通信,也要保证通信可靠,TCP的道理应该也是一样的。3、通信之前,三次握手。可以这样认为:a、甲问乙一个问题;b、乙回答甲的问题,同时问甲一个问题;c、甲再回答乙的问题。这样证明二者连接正常了,可以进行数据传输了。4、通信是可靠的,也就是说,甲如何确认乙收到了自己发的信息? 甲乙通信的信息中有两个字段,SendNum和AckNum,SendNum表示向对方问第几个问题,AckNum表示收到了对方的问题,回答对方第几个问题。注意:这种回答方式很特殊,别人问什么,我就把问题重复一边作为回答。5、甲. 阅读全文
posted @ 2014-02-28 18:55 Andy Niu 阅读(945) 评论(0) 推荐(0) 编辑
【M16】谨记80-20法则
摘要:1、开始编写代码时,不要过多考虑效率,而应该首先考虑逻辑的清晰性和代码的可读性。2、后期通过测试找到效率的瓶颈所在,而不是靠猜测。然后,针对性地去解决。也就是80%的时间去解决这20%的代码。 阅读全文
posted @ 2014-02-25 20:16 Andy Niu 阅读(234) 评论(0) 推荐(0) 编辑
【M8】了解各种不同意义的new和delete
摘要:1、首先考虑new operator,new operator 可以认为做了三件事情:a、调用operator new分配一块内存;b、在这块内存上调用构造方法构造对象;返回指针。2、operator new的声明如下: void* operator new(size_t size) 和C中的malloc一样,operator new只负责分配内存。3、考虑,string* ps = new string("hello"); 相当于做了下列事情: a、void* memory = operator new (sizeof(string)); b、在*memory上面,调用s 阅读全文
posted @ 2014-02-25 20:05 Andy Niu 阅读(414) 评论(0) 推荐(0) 编辑
【转】C++笔试题汇总
摘要:原文:http://www.cnblogs.com/ifaithu/articles/2657663.htmlC#C++C多线程面试1.static有什么用途?(请至少说明两种)1)在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。2) 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。3) 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用2.引用与指针有什么区别?1) 引用必须被初始化,指针不必。2) 引用初始化以后不能被改变,指针 阅读全文
posted @ 2014-02-25 19:21 Andy Niu 阅读(342) 评论(0) 推荐(0) 编辑
【转】c++笔试题
摘要:原文:http://blog.csdn.net/dongfengsun/article/details/1541926①链表反转单向链表的反转是一个经常被问到的一个面试题,也是一个非常基础的问题。比如一个链表是这样的: 1->2->3->4->5 通过反转后成为5->4->3->2->1。最容易想到的方法遍历一遍链表,利用一个辅助指针,存储遍历过程中当前指针指向的下一个元素,然后将当前节点元素的指针反转后,利用已经存储的指针往后面继续遍历。源代码如下:struct linka {int data;linka* next;};void revers 阅读全文
posted @ 2014-02-25 19:19 Andy Niu 阅读(663) 评论(0) 推荐(0) 编辑
【M21】利用重载技术避免隐式类型转换
摘要:1、考虑UPint 的加法+,UPint a, b, result; 为了使result = a+10; result= 10+a; 都能通过编译,操作符重载如下: const UPint operator+(const UPint& lhs, const UPint& rhs); 注意:不能使用成员操作符,否则result= 10+a;编译错误,因为隐式类型转换不能转换为this指针。2、在result = 10+a;调用的过程中,10会隐式转换为UPint(条件是UPint单一形参构造方法不是explicit),这导致临时对象的产生,效率降低。3、怎么解决这个问题呢? 增加 阅读全文
posted @ 2014-02-25 19:15 Andy Niu 阅读(328) 评论(0) 推荐(0) 编辑
【M6】区别increment/decrement操作符的前置(prefix)和后置(postfix)形式
摘要:1、考虑++(--的情况是一样的),前置是累加然后取出,后置是取出然后累加。2、重载方法根据形参表的不同区分,问题来了,前置和后置形式都没有形参,因此没法区分。怎么办? 对于后置增加一个形参int,在方法内并不使用这个形参,因此去掉形参名。3、考虑UPint(unlimited precision int)类,对于前置,返回引用,实现如下: UPint& UPint::operator++() { *this+=1; return *this; }4、考虑后置,后置返回老的对象。为了保证前置和后置的结果一致性,和代码的复用,使用后置调用前置。如下: const UPint... 阅读全文
posted @ 2014-02-25 18:54 Andy Niu 阅读(642) 评论(0) 推荐(0) 编辑
【M7】千万不要重载&&,||和,操作符
摘要:1、C++对于真假值表达式采用“骤死式”评估方法,比如&&,||。 if( p!=NULL&& strlen(p)>10) 如果p为NULL,后面的strlen不会被执行。 if(index upper) 如果index += -= *= /= %= ^= &= |= > >>= = && || ++ -- , ->* -> () []7、对于允许重载的操作符,必须有个好理由,才去重载。 阅读全文
posted @ 2014-02-25 18:29 Andy Niu 阅读(839) 评论(0) 推荐(0) 编辑
【M22】考虑以操作符复合形式(op=)取代其独身形式(op)
摘要:1、对于内置类型,x = x+y 与x+=y的结果相同。2、x=x+y 与 x+=y的结果相同,但二者做的事情差别很大。 a、x=x+y做的事情:方法内有个局部对象,值为x+y,返回局部对象,返回值是个临时对象,这个临时对象赋值给x。 b、x+=y做的事情:直接在x上操作,修改x的内容,并返回x的引用。3、从上面的分析可以知道,操作符复合形式(+=)比单独形式(+)效率高很多,复合形式避免了局部对象和临时对象的构造和析构,以及对x的copy赋值。4、为了避免重复代码和保持代码的一致性,应该让+调用+=,如下: template const T operator+(const T& l. 阅读全文
posted @ 2014-02-24 21:03 Andy Niu 阅读(287) 评论(0) 推荐(0) 编辑
String类的实现
摘要:1、在类中可以访问private成员包括两层含义:可以访问this指针的private成员;可以访问同类对象的private成员。2、这里的String可以认为是个资源管理类,内部有个char指针,在堆上分配对象,而且对于String应该是深复制,不是复制指针,而是要复制指针指向的内容。String类的定义(头文件): 1 #ifndef String_H_ 2 #define String_H_ 3 class String 4 { 5 public: 6 String(const char* src); 7 String(const String& rhs); 8 String&a 阅读全文
posted @ 2014-02-24 19:51 Andy Niu 阅读(374) 评论(0) 推荐(0) 编辑
理解 strcpy方法
摘要:1 char* strcpy(char* strDest, const char* strSrc)2 {3 assert((strDest!=NULL) && (strSrc !=NULL)); //strDest和strSrc不为空4 char* address = strDest; //保存strDest,用于返回5 while( (*(strDest++) = *(strSrc++)) != '\0' ); //逐个字符赋值6 return address; //返回地址 7 }注意:1、栈上的char数组,数组名就是一个指针,这个指针的指向不... 阅读全文
posted @ 2014-02-24 19:01 Andy Niu 阅读(250) 评论(0) 推荐(0) 编辑
多线程笔试
摘要:1、首先考虑,什么情况下使用多线程? 第一种情况:做事情A的过程中,顺便去做事情B,不需要B完成,可以接着做A余下的部分。这种情况下,对于事情B启动一个线程,往往需要传入一个回调方法,等事情B完成后,在主线程上执行回调方法。 第二种情况:事情A和事情B同时做,他们访问同一块数据,需要对这块数据加锁。2、考虑下面的需求,两个线程t1,t2,修改同一个数据,t1每次增加1,t2每次减2,怎么做? a、首先肯定要准备两个方法Add1和Sub2,分别传给t1,t2; b、准备共享资源和互斥体mutex(也就是值为1 的信号量); c、Add1和Sub2方法内分别加锁,在加锁的语句块内,修改共... 阅读全文
posted @ 2014-02-21 20:01 Andy Niu 阅读(540) 评论(0) 推荐(0) 编辑
C++ 中复杂的声明
摘要:1、方法也是有类型的,方法的类型由返回类型和形参表决定。比如int F (int)的类型就是去掉方法名,int (int)。2、对于方法类型,在返回类型和形参表之间,加上一个名称F,就表示一个特定的方法F。3、思考,如果我在返回类型和形参表之间,加上一个指针变量呢? 表示指向这一类方法的指针。即int (*P) (int),需要特别注意的是,必须使用括号把*P括起来。如果没有括起来,int *P(int),从编译器的角度理解,就变成了返回int指针的方法声明。4、那么接着思考,方法指针也是指针,既然方法能够返回其他指针,当然也可以返回方法指针。 方法指针的类型就是去掉指针名称,int(*).. 阅读全文
posted @ 2014-02-21 19:06 Andy Niu 阅读(726) 评论(0) 推荐(0) 编辑
指向成员的指针
摘要:1、从封装的角度看,类可认为是一个命名空间,名称就是类名。类中有两个成员:字段和方法。2、指针可以指向任何对象,当然也可以指向类中的字段和方法。那么该如何指向类中的字段和方法呢?3、分别是: int Animal::*pData = &Animal::_age; int (Animal::*pFun)() = &Animal::getAge;4、我们定义指向类中字段或者方法的指针,往往是为了通过指针和对象绑定一起,去修改字段或者访问方法,这种情况下,我们不需要直到类的字段名或者方法名。该怎么做呢? 既然是指向字段或者方法的指针,通过*解引用,就得到了字段或者指针。对于对象使用. 阅读全文
posted @ 2014-02-21 18:33 Andy Niu 阅读(225) 评论(0) 推荐(0) 编辑
指针与引用的操作符
摘要:1、对于指针*,声明或者定义的时候,表示变量为指针。在其他的地方,如果是单目操作,表示对指针解引用,如果是双目操作,表示乘法。2、对于引用&,声明或者定义的时候,表示变量为引用。在其他的地方,如果是单目操作,表示取地址,如果是双目操作,表示按位与。3、声明或者定义指针的时候,*可以紧靠类型,也可以紧靠变量,二者是等价的。但是推荐的编码风格是,紧靠变量。为什么? a、紧靠类型,会产生错觉。比如int* i, j; 有些人会认为定义了i,j两个int指针。而实际情况是i是int指针,j是int变量。使用int *i, j; 可以避免产生这种错觉。 b、考虑指向成员的指针,从封装的角度看,类 阅读全文
posted @ 2014-02-21 18:09 Andy Niu 阅读(641) 评论(0) 推荐(0) 编辑
char指针
摘要:1、在C语言中,没有字符串类型,因此使用char指针表示字符串。2、那么问题来了,使用char* 表示字符串,到哪里是结尾呢?因此需要一个特殊的字符作为哨兵,类似迭代器中的end(),这个哨兵就是'\0',注意不是字符0.3、对于文本字符串,编译器会自动添加\0。4、对于字符数组的赋值,如果不使用文本字符串,需要用户在尾部添加字符\0。对于其他类型的数组,没有\0的概念。5、对于char指针,C语言提供了一系列方法,如strlen,strcmp。这些方法有个特点,都是假定最后一个字符为\0。因此对于char指针,我们要保证最后一个字符是\0。6、考虑sizeof,对于指针,取值 阅读全文
posted @ 2014-02-20 21:39 Andy Niu 阅读(3265) 评论(0) 推荐(1) 编辑
软件测试
摘要:1、整个流程:需求分析-->概要设计-->详细设计-->编码实现-->单元测试-->集成测试-->系统测试-->验收测试。2、单元测试覆盖率包括:语句覆盖,判定覆盖,条件覆盖,判定条件覆盖,条件组合覆盖,路径覆盖。 阅读全文
posted @ 2014-02-20 21:09 Andy Niu 阅读(159) 评论(0) 推荐(0) 编辑
网络应用层协议
摘要:ftp文件传输协议21telnet远程登录协议23smtp简单邮件传输协议25http超文本传输协议80pop3邮局协议第3版本1101、t=transfer,传输的意思。2、stmp是发邮件协议,包括两部分,客户端到自身服务器,服务器转发到目标服务器。3、pop3是接收邮件协议,通过客户端到服务器上把邮件取下来,需要用户名和密码。 阅读全文
posted @ 2014-02-20 21:05 Andy Niu 阅读(569) 评论(0) 推荐(0) 编辑
BOOL,int,float,指针变量与零值比较的if语句
摘要:1、注意这里说的是,与零值比较,而不是与零比较。2、对于int类型,与零值比较就是: if(var == 0) //零值3、对于bool类型,零值表示false,任何非零值表示true,因此使用: if(!var) //零值4、对于float,计算机无法表示准确的浮点数,比如大家都知道:1.0/3 * 3 !=1,因此需要判断变量是否大于一个很小的负数并且小于一个很小的正数。 const float f = 0.000001; if(var>=-f && var<f) //零值5、对于指针,零值就是null,因此应该与null比较。 if(var ==null) / 阅读全文
posted @ 2014-02-20 20:49 Andy Niu 阅读(929) 评论(0) 推荐(0) 编辑
有关单向链表的题目
摘要:1、编码的关键是思路,思路不对,不可能编出正确的代码。考虑下面两个关于单向链表的题目:2、单向链表,如何判断是否构成环形? a、思路一:常规做法,建个集合,遍历单向链表,集合没有包含元素,添加进去集合,集合包含元素直接返回true,跳出遍历,返回false。 b、思路二:使用快慢指针,建立两个节点,n1从head开始,n2从head->next开始,while(n1 && n2),n1每次走一步,n2每次走两步。如果n2先走到null,说明没有环。如果n1==n2,说明有环,n2又从后面追上来。3、对于单向链表,查找倒数第K个节点。 a、思路一:先计算节点个数,倒数第K个 阅读全文
posted @ 2014-02-20 20:29 Andy Niu 阅读(272) 评论(0) 推荐(0) 编辑
main方法执行之前,做什么事
摘要:1、我们知道程序的入口是main方法,那么在执行main方法之前,需要做些什么准备工作呢?2、main方法执行之前,必须要把non-local static对象构造完成。static对象有:全局对象,命名空间中的对象,类的static对象(从封装的角度看,类也是一个命名空间),方法内的static对象,其中方法中的static对象是local static对象,其他的是non-local static对象,这些对象分配在全局区,程序结束才释放内存。3、local static对象直到方法被调用的时候,才进行初始化,而且只初始化一次。non-local static必须在main方法执行之前,进 阅读全文
posted @ 2014-02-20 20:05 Andy Niu 阅读(4567) 评论(0) 推荐(0) 编辑
C++复制控制
摘要:1、复制控制包括:copy构造,copy赋值,析构方法。2、没有声明任何构造方法,编译器自动生成一个default构造方法。对于copy构造,copy赋值和析构方法,没有声明,编译器会自动合成一个。3、合成的copy构造,做的事情是:逐个字段初始化,将新对象初始化为原对象的一个副本。所谓的逐个成员初始化,只是指实例字段,不包括static字段,因为static字段是共享的。如果字段是值类型,直接赋值。如果字段是类类型,递归调用copy构造方法。有个情况很例外,一般情况下,不能复制数组,但是对于类中的数组,合成copy构造将复制数组中的每一个元素。4、合成的copy赋值,做的事情:除了stati 阅读全文
posted @ 2014-02-20 19:28 Andy Niu 阅读(748) 评论(0) 推荐(0) 编辑
C++访问权限
摘要:1、C++类本身没有访问权限的概念,就是class Base。2、类成员的访问权限有:public、protected、private3、类的继承方式有:public、protected、private 阅读全文
posted @ 2014-02-20 18:56 Andy Niu 阅读(280) 评论(0) 推荐(0) 编辑
C++ struct与class
摘要:1、相对于C中struct,C++做了很大的扩充。基本上和class 差不多。只有一些细节上的差别。2、对于成员的默认访问权限,class是private,struct是public。需要注意的是,程序中应该明确指出访问权限,不要依赖默认的访问权限。对于其它默认的情况也是一样,尽量明确指出来,这是一个良好的编程习惯,增加代码的可读性。3、对于默认的继承方式,class是private,struct是public。需要注意的是,class可继承class,也可继承struct。struct可继承struct,也可继承class。默认的继承方式取决于子类是struct还是class。和上面一样,这 阅读全文
posted @ 2014-02-20 18:53 Andy Niu 阅读(1972) 评论(0) 推荐(0) 编辑
char数组与char指针
摘要:1、以字符串形式出现的,编译器会在结尾自动添加\0,思考,为什么? 存在的C语言方法,如strlen(s),计算字符串的长度,其中s指针。strlen要计算字符串长度,必须知道哪里是结尾,因此使用\0表示结尾。只有字符数组才有\0的概念,其它类型(int)的数组没有这个概念。因为其他类型的数组或者... 阅读全文
posted @ 2014-02-17 20:48 Andy Niu 阅读(58951) 评论(4) 推荐(1) 编辑
Python 类型的分类
摘要:1、存储模型,对象可以保存多少个值。如果只能保存一个值,是原子类型。如果可以保存多个值,是容器类型。数值是原子类型,元组,列表,字典是容器类型。考虑字符串,按道理,字符串应该是容器类型,因为它包含多个字符。但是,Python中没有字符类型,也就是没有字符的概念,因此,把字符串归为原子类型。2、更新模型,对象的值是否可以更新。Python彻底分离了引用和实体,比如a=1; b=a; b=2; 可以认为,a指向的内存内容不允许修改,现在b也指向这块内存,那么我要修改b,该怎么办呢? 只能是重新分配一块内存,内容为2,然后修改b的指向,让b指向这块内存。a还是指向原来的内存,内容不变。 思考,P.. 阅读全文
posted @ 2014-02-16 22:22 Andy Niu 阅读(2735) 评论(0) 推荐(0) 编辑
stack对象与heap对象
摘要:从高地址到低地址,分别是stack,heap,static object,stack地址往下增长,heap地址往上增长。只要记住:stack栈顶地址反而小,就知道往下增长了。禁止产生堆对象1、产生堆对象使用new operator,可认为new operator有三个过程: a、使用operator new操作符搜索可用的内存,分配一块内存; b、在这块内存上,调用构造方法构造一个对象; c、返回地址。2、要禁止产生堆对象,可以声明类的operator new为private,禁止分配内存就好了。为了保持一致性,将operator delete也重载为private。3、注意:new o... 阅读全文
posted @ 2014-02-13 20:01 Andy Niu 阅读(940) 评论(0) 推荐(1) 编辑
【M15】了解异常处理(exception handling)的成本
摘要:1、为了在运行期处理异常,程序必须做大量额外的工作。比如,即使抛出异常,也必须保证离开作用域的栈上对象执行析构方法。因此,必须记录try语句的进入点和离开点,记录catch语句能够处理的异常等。这就意味着,程序目标码变大,执行速度慢。2、即使从未使用任何异常处理,还是必须要付出最低代价,付出一些空间,放置某些数据结构,付出一些时间,保持数据结构的正确性。3、即使自己的程序没有使用throw,try,catch语句,使用的其他程序库可能有异常处理,因此也要付出代价。4、对于try语句,没有异常抛出的情况下,代码膨胀5%-10%,速度也下降这个数。5、如果抛出异常,影响很大,速度可能会比正常情况下 阅读全文
posted @ 2014-02-12 19:21 Andy Niu 阅读(373) 评论(0) 推荐(0) 编辑
【M20】协助完成“返回值优化(RVO)”
摘要:1、方法返回对象,会导致临时对象的产生,这降低了效率,const Rational operator* (const Rational& lhs,Rational& rhs)。有没有什么解决办法呢?2、试图返回引用,方法内的局部对象,在方法执行完后销毁,这个引用指向垃圾。不可行。3、试图返回指针,这导致奇怪的语法Rational c = *(a*b); 并且要求客户执行delete,这不合理。就算客户正确执行delete,有些情况,方法返回值没有暴露指针,客户无法执行delete,比如:Rationald = *(a*b*c); 不可行。4、因此,必须返回对象。那该怎么办呢? 阅读全文
posted @ 2014-02-12 18:59 Andy Niu 阅读(346) 评论(0) 推荐(0) 编辑
对象切割与临时对象
摘要:1、判断是copy构造还是copy赋值,不是看是否有赋值操作符=,而是看对象当前是否已经有值了。如果没有值,就是copy构造。如果已经有值了,就是copy赋值。2、对象赋值的时候,源端与目标端类型不吻合,肯定要进行一次适配(而且只能是一次),中间产生一个临时对象。3、比如:Person p; p = 6; copy赋值的时候,要求rhs是个const Person&,显然6不是。因此,这里适配一下,用6构造一个临时对象,然后rhs指向这个临时对象。 那么接着思考,子类对象赋值给父类对象,会造成对象切割。那么这个过程是否产生临时对象呢?Person p; Student s; p=s; 阅读全文
posted @ 2014-02-12 18:34 Andy Niu 阅读(728) 评论(0) 推荐(0) 编辑
【M1】仔细区别pointers和references
摘要:1、引用必须初始化,而且不能修改指向,这一点和const对象十分相似。2、引用和指针用法不同,对于引用int& ri = a; rhs是个对象,引用前面加&;对于指针,int* pi = &a; rhs是个对象地址,指针前面加*。注意:引用往往是用指针实现的,从int& ri = a; 可以认为a赋给ri,再取地址。3、引用是一个对象的别名,不能指向为空,而且自始至终是这个对象的别名。指针是地址,可以指向为空,也可以指向不同的对象。4、考虑对引用初始化:引用是一个对象的别名。引用不能指向为空,但是通过一定技巧,可以让引用指向为空。考虑,先让指针指向为空(0),解 阅读全文
posted @ 2014-02-12 18:13 Andy Niu 阅读(424) 评论(0) 推荐(0) 编辑
【M19】了解临时对象的来源
摘要:1、首先,确认什么是临时对象。在swap方法中,建立一个对象temp,程序员往往把temp称为临时对象。实际上,temp是个局部对象。C++中所谓的临时对象是不可见的,产生一个non-heap对象,并且没有命名,便是一个临时对象。2、临时对象的来源有:隐式类型转换,方法返回值,抛出异常的时候。3、隐式类型转换:在初始化或者赋值的过程中,如果类型不匹配,需要一个适配的临时对象,编译器会构造这个临时对象,使调用成功。 注意:这种适配,只能执行一次,不能执行多次。为什么?假如可以执行多次,从一个对象到另一个对象,存在很多转换路径,编译器不可能找出所有的路径。就算可以找出所有的路径,存在多条转换路径. 阅读全文
posted @ 2014-02-11 20:24 Andy Niu 阅读(423) 评论(0) 推荐(0) 编辑
【M13】以by reference 方式捕捉exceptions
摘要:1、catch语句的参数有三种方式:by pointer,by value,by reference。2、首先考虑,by pointer。这意味着抛出端必须抛出一个对象的地址。那么问题来了: 如果这个对象分配在栈上,离开作用域,对象销毁,catch语句中指针指向一堆垃圾。 因此,这个对象不能分配在栈上,也就是说,离开了作用域对象仍然存在,没有销毁。那就只能是static对象,或者是heap对象。那么问题又来了,在catch语句的客户端,客户到底要不要执行delete呢?客户不知道这个对象是static还是heap对象。如果执行delete,而抛出端的对象是static,对不是在heap上分.. 阅读全文
posted @ 2014-02-11 19:38 Andy Niu 阅读(427) 评论(0) 推荐(0) 编辑
【M12】了解“抛出一个exception”与“传递一个参数”或“调用一个虚函数”之间的差异
摘要:1、方法参数的声明语法和catch语句的语法是一样的,你可能会认为主调方法调用一个方法,并向其传递参数,与抛出一个异常传递到catch语句是一样的,是的,有相同之处,但也有更大的不同。2、主调方法调用一个方法,控制权转移,被调方法执行完,控制权最终还会返回到主调方法。但是,抛出异常到达catch语句,控制权不会再回到抛出端。3、那么问题来了,抛出异常到达catch语句,控制权不再会到抛出端,这意味着,抛出的异常离开了作用域,自动销毁,那么catch语句还怎么捕获异常对象呢? 解决办法是:建立一个临时对象,对抛出的异常进行copy构造。特别注意的是,不管什么情况,这个临时对象是必不可少的。根本. 阅读全文
posted @ 2014-02-11 18:56 Andy Niu 阅读(655) 评论(0) 推荐(0) 编辑
【48】认识template元编程
摘要:1、TMP(template metaprogramming),模版元编程有两个效力:第一,它让某些事情更容易;第二,可将工作从运行期转移到编译期。 阅读全文
posted @ 2014-02-10 20:18 Andy Niu 阅读(326) 评论(0) 推荐(0) 编辑
【44】将与参数无关的代码抽离templates
摘要:1、template是产生代码的代码,这就意味着源码看起来很少,生成的目标码大量膨胀。2、考虑,如果两个方法有重复代码,我们会新建一个方法,把重复的代码放进去,原先两个方法调用第三个方法。如果两个类有重复代码,我们把重复代码移到一个新的类中,通过继承或者复合,避免重复。3、但是在template中,这种重复是隐晦的,只有一份template代码,可能会生成一系列重复的代码。考虑矩阵模板类,有两个模版形参:矩阵元素的类型T和矩阵的大小S。4、SquareMatrix 和SquareMatrix 会实例化两个模板类,这两个模板类有大量重复代码,比如:invert方法。5、如何解决呢? 建立一个模. 阅读全文
posted @ 2014-02-10 20:03 Andy Niu 阅读(825) 评论(0) 推荐(0) 编辑
【23】宁以non-member、non-friend替换member函数
摘要:1、non-member方法与member方法没有本质区别,对于编译器来说,都是non-member方法,因为member方法绑定的对象,会被编译器转化为non-member方法的第一个形参。non-member方法与member方法唯一的区别是:member方法封装性更差,因为它可以访问private成员。2、根据面向对象的要求,数据与方法应该和对象捆绑在一起,这意味着应该使用member方法。其实,这个建议是错误的。为什么?3、首先,non-member、non-friend方法提供更大的封装性。4、其次,考虑下面的需求,我只需要类中的一个方法。如果是member方法,必须把整个class 阅读全文
posted @ 2014-02-10 19:16 Andy Niu 阅读(1024) 评论(0) 推荐(0) 编辑
【22】将成员变量声明为private
摘要:1、为什么要将成员变量声明为private,语法一致性,只通过方法暴露接口。2、使用方法,可以对成员变量更精确的控制。比如:为所有可能的实现提供弹性,不同实现可以替换;控制可读可写;验证约束条件;处理事前和事后状态;在多线程环境执行同步控制。3、public会破坏成员变量的封装性,程序中到处都可修改成员变量。将成员变量声明为private,暴露一个方法接口,可以统一管理。4、对于成员变量,protected并不比public更具封装性。 阅读全文
posted @ 2014-02-10 18:41 Andy Niu 阅读(519) 评论(0) 推荐(0) 编辑
【21】必须返回对象时,别妄想返回器reference
摘要:1、考虑有理数Rational,有个友元操作符*,返回Rational对象。返回对象,导致临时对象的构造,析构。效率低,因此会想返回方法内局部对象的引用,这种方法不可行。为什么?2、调用方法是在stack上执行,方法执行完毕,局部对象销毁。假如返回方法内局部对象的引用,方法执行完,局部对象销毁,这时候,引用指向一堆垃圾。3、你可能会想,我在heap上构造一个对象,返回引用。这也不可行,首先,要求客户端负责delete,这不合理。其次,退一步说,就算客户负责,执行delete。但是有些情况,客户无法执行delete。比如:Rational d = a*b*c; a*b的结果没有暴露出来,客户无法 阅读全文
posted @ 2014-02-10 18:21 Andy Niu 阅读(303) 评论(0) 推荐(0) 编辑

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示