上一页 1 ··· 18 19 20 21 22 23 24 25 26 ··· 58 下一页
  2014年3月25日
摘要: 1、程序库的设计是一种权衡的结果。体积小,速度快往往不能移植。可移植,通用的程序库往往意味着冗余和效率低下。2、因此,选择程序库的时候,需要进行取舍。比如:iostream和stdio。iostream具有类型安全性,可扩充,而stdio的效率更高。注意,对性能评估的时候,不要猜,应该进行多次实验进行确认。 阅读全文
posted @ 2014-03-25 18:45 Andy Niu 阅读(168) 评论(0) 推荐(0) 编辑
摘要: 1、基本思想就是:如果将来肯定要做某件事,并且这件事情耗时,提前把东西准备好,先做一部分。常用的使用场景有:2、考虑一个大的数据集合,集合中元素不断变化。经常要取出里面的最大值,正常的做法是:每次调用的时候,计算出最大值,这可能是一个耗时的操作。既然是经常取出最大值,那我就实时(每次对集合增删改的时候)更新最大值,需要的时候直接就返回最大值了。3、考虑stl中的vector,vector有5个元素,假设vector的内存刚好容纳5个元素,现在增加一个元素。那就意味着必须分配一块6个元素的内存,把原来的5个元素和新增的1个元素copy过来。这显然效率很低。解决办法是:预留一些内存。4、较快的速度 阅读全文
posted @ 2014-03-25 18:20 Andy Niu 阅读(420) 评论(0) 推荐(0) 编辑
摘要: 1、缓式评估其实就是拖延战术,直到逼不得已的时候才去计算。缓式评估的使用场景有:2、引用计数,考虑String,String是一个内含char指针(char指针以'\0'结束)的资源管理类,正常情况下,String的copy构造和copy赋值都是深层copy,也就是对char指针指向的内容做一个副本,这个效率显然很低。考虑String s2 = s1; 后面的代码可能只是读取s2,没有必要做深层copy,s2与s1可以共享一份数据,也就是使用引用计数,来实现String。但是,当修改String的时候,必须做一个深层copy,也就是拖延战术。3、区分读与写,考虑cout< 阅读全文
posted @ 2014-03-25 17:59 Andy Niu 阅读(448) 评论(0) 推荐(0) 编辑
摘要: 1、考虑二维数组,在C++中,以先行后列的方式存储连续的数组元素。也就是同一行的元素在一起,同一列的元素之间有间隔,且间隔相同。理想情况下,二维数组的元素是随机访问的,可以直接定位,即i*列数+j。因此,对于二层for循环访问二维数组的元素,先行后列与先列后行的效率应该是一样的。但是,二维数组的数据往往需要多个内存分页才能容纳,由于C++同一行的元素在一起,先行后列,更符合空间局部性,可以减少换页。因此,先行后列的效率高。2、考虑二层for循环,有大循环和小循环。大循环在内部效率高。为什么?可简单地认为,跨越循环层是个耗时耗资源的操作,大循环在内部,跨越循环层的次数少。从另一方面理解,大循环在 阅读全文
posted @ 2014-03-25 17:57 Andy Niu 阅读(2400) 评论(0) 推荐(0) 编辑
  2014年3月12日
摘要: 1、编译器必须实现出C++语言的特性。一般情况下,我们只需要使用这些特性就好了,不需要关心内部的实现细节。但是,有些特性的实现,会对对象的大小和成员方法的执行速度造成影响。因此,有必要了解内部实现的细节。2、首先考虑虚方法,虚方法是用来实现多态的。多态是指对于指针和引用,表面类型和真实类型不一致的情况下,调用真实类型的虚方法。3、虚方法有关的实现细节为: a、父类有一个虚方法表(vtbl),可以认为是一个方法指针的数组(这里注意:对于数组,我们知道元素的类型必须一致,虚方法表中的虚方法类型是不一样的,这里进行了特殊处理),方法指针指向父类的虚方法。 b、子类整体拷贝父类的虚方法表,对于重写.. 阅读全文
posted @ 2014-03-12 18:00 Andy Niu 阅读(606) 评论(0) 推荐(0) 编辑
摘要: 1、无论是int,还是uint在底层的存储方式是一样的,都会存在溢出和借位的现象,可以认为是个环,有以下几个情况: a、两个数相加,溢出会变成一个小的数。 b、两个数相减,不够减,借一位。 c、求一个负数,拿0减去对应的正数。注意:正6是0x0000 0006;负6可不是0x1000 0006,而是0 - 0x0000 0006 = 0xffff fffa2、对于int,uint存储方式相同,不同的只是编译器把它当成什么数来解释。比如: int a = 0xffff fff9; unsigned int b = 0xffff fff9; 对于a,把它当成int解释,就是-7;对于b... 阅读全文
posted @ 2014-03-12 15:30 Andy Niu 阅读(401) 评论(0) 推荐(0) 编辑
摘要: 1、Python彻底分离了对象和引用,可以认为内存中的对象都是不可修改的,每次修改引用,相当于在堆上重新创建一个对象,引用指向新对象。2、对于数值和字符串,修改意味着引用指向一个新对象。3、集合中的元素都是引用。考虑元组,元组中的引用不能增加删除,也不能修改引用的指向。但是元组本身也是个引用,可以指向另一个元组。4、考虑列表,列表中的引用可以增加删除,也可以修改引用的指向。列表本身也是个引用,也可以指向另一个列表。5、考虑字典,字典的key不能修改指向,value可以修改指向。字典本身也是个引用,也可以指向另一个字典。6、考虑下面的情况,listB = listA, listB 与 listA 阅读全文
posted @ 2014-03-12 15:27 Andy Niu 阅读(3880) 评论(0) 推荐(0) 编辑
  2014年3月10日
摘要: 1、进程是操作系统进行资源分配和调度的基本单位,线程是CPU调度的基本单位,是进程中一个单一顺序的执行流。2、把进程当成做一件事情,操作系统管理进程,负责调度进程。具体怎么做?是进程的事。一个进程至少有一个主线程,可以有多个辅助线程,真正做事的是线程。进程做的事情:可以是一个线程按顺序一步一步做,也可以启动多个线程,协作完成。3、进程有一块内存,也就是可执行文件装载到操作系统中,从上到下大致为:栈,堆,全局存储区,常量存储区,代码区。而线程可以认为是一个执行流,每个线程都有一个自己的调用堆栈,可以访问进程中的资源,对于共享资源需要进行同步控制。而一个进程是不能访问另一个进程的资源,只能通过进程 阅读全文
posted @ 2014-03-10 15:27 Andy Niu 阅读(598) 评论(0) 推荐(1) 编辑
摘要: 1、考虑下面的需求,对于vec开始的时候有1000个元素,后来只有10个元素,那么vec的capacity至少还是1000,后面的990个内存单元,没有使用,但是还被vec霸占着。如何释放这些内存呢?2、我们知道,vector进行copy构造的时候,根据rhs 的size进行分配内存。因此,我们可以建立一个临时对象,然后交换一下就可以了。如下: vector(vec).swap(vec); vector(vec) 是个临时对象,可认为capacity为10,而vec的capacity为1000,二者交换后,vec的capacity为10,临时对象析构。3、这里需要注意两点: a、临时对象... 阅读全文
posted @ 2014-03-10 12:13 Andy Niu 阅读(488) 评论(0) 推荐(0) 编辑
摘要: 1、首先明白capacity与size的概念,capacity表示当前可以容纳多少个元素,size表示当前有多少个元素。为了避免频繁地分配内存,vector预留了一些内存。也就是说:sizecapacity,重新分配内存,把原来的数据copy过来,修改capacity = n。 b、如果ncapacity,重新分配内存,把原来的数据copy过来,在尾部补齐元素。没有指定构造方法,使用default构造方法。 阅读全文
posted @ 2014-03-10 11:27 Andy Niu 阅读(397) 评论(0) 推荐(0) 编辑
上一页 1 ··· 18 19 20 21 22 23 24 25 26 ··· 58 下一页