常见误区和陷阱,草稿
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,回溯,这个溯字,其实又是个生僻字,不大能体现这个算法的情景。其实叫返跟算法,更容易描述这个算法的运用场景,只要知道这个算法会返回并继续跟踪,那么很多问题,会准确快速的使用到这个算法。

浙公网安备 33010602011771号