常见误区和陷阱,草稿

1,左右值

2.继承是为了复用

3.句柄

4,is-a

5,引用变量不占内存

6.随机存储。

7,递归算法时间复杂度是太高。所以尽量不要使用递归。

8,predicate 谓词是谓语

9,无条件的空间换时间

10.同步阻塞。

11.socket

12.render 在前端的翻译

13,backstack 翻译为回溯

14.依赖倒置,Dependence Inversion,英文本身的名字就起的差劲,除非这个短语在英文中有其他引申意思,

非常明显 Dependence Inversion 改为Dependence interface,依赖抽象,不好吗?这么简单名字,1秒钟就可以明白,而依赖倒置,知道这个名词的几年后,我才知道它说的是什么。

 

1,左右值

L-value中的L指的是Location,表示可寻址。A value (computer science) that has an address.
R-value中的R指的是Read,表示可读。in computer science, a value that does not have an address in a computer language.

C/C++语言中可以放在赋值符号左边的变量,即具有对应的可以由用户访问的存储单元,并且能够由用户去改变其值的量。左值表示存储在计算机内存的对象,而不是常量或计算的结果。或者说左值是代表一个内存地址值,并且通过这个内存地址,就可以对内存进行读并且写(主要是能写)操作;这也就是为什么左值可以被赋值的原因了。相对应的还有右值:当一个符号或者常量放在操作符右边的时候,计算机就读取他们的“右值”,也就是其代表的真实值。简单来说就是,左值相当于地址值,右值相当于数据值。右值指的是引用了一个存储在某个内存地址里的数据。



区分左值右值的真正说法是:能否用“取地址&”运算符获得对象的内存地址。
对于常量,它可能被编码到机器指令的“立即数”中,所以是没办法用“取地址&”运算符;

2.继承

 本末倒置,继承不是为了复用,继承是建模的一个手段,继承恰恰是为了不能复用某部分而产生的手段。

3.handle

handle,根据语境的不同,应该理解为不同的意思。

直接用指针来沟通吧。句柄,什么玩意。

 

4,is-a

理解为行为像,比是一个更恰当。

 

5.引用占不占内存

int a=34;
int& b=a;
int * c=&a;


57 int a=34;
0x00401604 movl $0x22,0x4(%esp)
58 int& b=a;
0x0040160C lea 0x4(%esp),%eax
0x00401610 mov %eax,0xc(%esp)
59 int * c=&a;
0x00401614 lea 0x4(%esp),%eax
0x00401618 mov %eax,0x8(%esp)

随便看下汇编后的指令就知道,必须有空间来存放被引用对象的地址。

不知道为什么会有不占空间的说法。可能是取引用的地址还是原数的地址。就臆测引用不占空间吧。

 

6.随机访问。randomaccess

解释为 立即访问 不是更好吗,直译到中文有语言障碍。

 

7.递归算法复杂度:递归时间效率和循环理论是一模一样的。

会计算算法时间复杂度之后,对这个疑惑的流行结论,计算了一下。果然有问题。

首先,

1)递归是思路,递归本身就包括,二分法,快排,等等各种算法。只不过问题本身的特点,他们递归时,下一个问题的复杂度是n/2.

2)就算是每次递归问题只缩小1的算法。下一个问题的复杂度是n-1  .。比如含洛塔,和树的遍历。也不是算法本身效率低。而是问题就复杂。

因为数据结构本身就包含2次递归。左右2个子树。如果能搞成一个递归,那就是n的时间复杂度了,如循环。

稍微想下就明白。二分是查一个数而已。快排是排序线性数字, 而遍历树,是遍历整个树,树的层次,增加是很恐怖的。

n-1递归算法,复杂度是2的n次方。看起来很吓人。但不是递归吓人,而是问题本身吓人。

如,访问一个3层的二叉树。 循环的复杂度是n,这个n是叶子。递归算法是2^n,这个n是层数。所以递归时间效率和循环理论是一模一样的。

循环访问。循环复杂度是n。

而用递归,复杂度是2^n.

但是。他们的n是不一样的。循环访问n是叶子的数量。3层叶子数量是7.  所以:n=7.T(7)=7

而递归的n才是层次,n=3. T(3)=2^3=8.,而递归的复杂度是一个近视值,精确的结果 自己计算为2^n-1+2n-2+1。 所以 T(7)=4+2+1=7.

所以递归的时间复杂度不是这个算法复杂,而是问题本身很大。10层二叉树。自己算算多少叶子。 

唯一的缺点就是递归用函数,需要嵌套调用函数,太深会导致栈满。

假如太深的递归,用递归算法,可以用栈数据结构,模拟函数递归。因为递归是不可多得的算法思路。

最最重要的是,一次可以递归解决的,不要搞成多个递归,要不然就是x^n了,递归能缩小下次计算规模的话,尽量缩小。因为不但运行要时间,而且函数压栈也是要空间的。还不如,函数里多个变量,减少运行次数,就等于减少空间和时间。

 

8,predicate 谓词是谓语

用汉语来说就是,程序员按某个容器成员大小排序了a容器。
如:sort(a.begin(),a.end(),isShorter),谓语是sort,宾语是a.begin(),a.end(),其中isShorter是谓语的定语,这里就翻译为谓词。
程序员按某个容器成员大小排序了a容器
主谓宾:程序员排序容器 you sort a.
谓语的定语(predicate 谓词) :按某个容器成员大小, isShorter

9,常见于数据库或类的设计中冗余的字段。

个人感觉开发时,除非冗余会带来可预见的性能可感知的提升。

否则先不必要冗余,冗余带来2个数据间的同步等问题,有bug隐患,而且,有时候冗余的字段,查询本身可能和非冗余差不多的性能,都是要查表。

先不冗余,可看需求,迭代开发加上。

 

10.网络一堆乱78遭的解释。

阻塞非阻塞:io操作,读或写,是否立即返回?是就是非阻塞,否就是阻塞。 立即返回就必须包括没有数据,那么返回没有数据的标识。

同步异步:是否有另外一个线程来处理io?否,就是同步。是,那么一般就是异步。   一个线程自己如何异步?所以肯定是其他线程或进程,当io完毕后,通过回调用户函数,或唤醒用户另外的线程,

iocp,就是系统,唤醒worker线程,达到异步。

而有些事件回调,就是通过回调,来达到异步。

 

11.socket 的 中文翻译。

不想说了,恩还是用linux下的概念来解释吧fd=socket();socket就是 socket: socket是一个五元组来标识的文件描述符:<源地址,源端口,目的地址,目的端口,使用的协议>用来读写数据。

 所以socket,要不直接用英文说明。中文就直接描述为  有2端地址和端口信息的文件

 

12.render,web前端,直接用了渲染这个意思。怎么说的。翻译没有一点问题。但是感觉用填充翻译过来非常好理解。怪老外吧。web的reader只是填充数据而已

 

13,回溯,这个溯字,其实又是个生僻字,不大能体现这个算法的情景。其实叫返跟算法,更容易描述这个算法的运用场景,只要知道这个算法会返回并继续跟踪,那么很多问题,会准确快速的使用到这个算法。

posted @ 2016-12-02 21:06  琴鸟  阅读(262)  评论(0)    收藏  举报