more effective c++ 读书笔记 第四章 效率

条款16
谨记80-20法则

这里作者谈的多是理念,比如,80%的资源被20%的代码所使用。所以大部分时候,我们所写的代码是平凡的,也就是说,在80%的时间里,他不会对整体效率有影响(有趣了)。大部分人对瓶颈的查找是猜,但是应该用正确的工具来测量。

条款17
考虑使用lazy evaluation

惰性求值的意思就是只有在被真正使用时才去做计算,比如写时复制这种特性。作者举了个例子:

string s1 = “hello”
string s2 = s1;
strng ctor 一般会使得s2拥有s1的副本,这里开销不小,会使用new 申请内存,然后复制。这是eager evaluation(急式评估),但其实可以先让s2和s1共享数据,当其中一个被修改时再去复制,这其实也就是享元模式。

对于读和写,这里比较难区分,比如cout<<s1[1]是读
s1[1] = 'a’是写,作者说后面会使用proxy class(代理类)解决。

缓式取出:指的是一个结构体字段的赋值可能来自网络或者某种IO,这时整体赋值是慢的,可以针对某个字段去赋值,即使用到了某个字段,才去进行IO操作赋值单独这个字段。
这个还是要看具体场景了。

表达式缓式评估:
比如有某个矩阵, m1, m2
计算m3 = m1 * m2可能计算量大,但是如果对于m3的使用只是cout<<m3[4],那么没有必要算出整个m3, 只需要算出第4行。

这里都是些理念的东西,需要工作中细细体会发掘了。

条款18
分期摊还预期的计算成本

这个跟上面的相反,上面的概念是能不做就不做, 这里是要提前做,这个就好像cache, 利用的是局部性原则,读一个数据,把一整行都读上来。又或者比如vector的扩张等。

条款19
了解临时对象的来源
void f(const string& str);

char* p = "test";
f(p);

这里由于参数不同,会使得p被隐式转换string,所以由此产生了string 临时对象,调用构造和析构函数。需要留意的现象是,只有按值传递和const ref时才会产生这种情况。比如:

void f(string& str);

char* p = "test";
f(p);

以上代码会编译失败。因为假设产生了临时对象,那么如果f内部可能对string有修改,那么修改只作用在临时对象上,实参则不受影响,所以c++禁止在non-const ref 参数上产生临时对象, const ref则可以,所以当看到一个const ref时,就有可能出现一个临时对象。
还有一种临时对象是返回值,此时需要注意返回值优化。

条款20
协助完成返回值优化 (NRO)
const Obj f(const Obj& lhs , const Obj& rhs)
{
	return Obj(lhs.data, rhs.data);
}

这里直接return 一个调用构造函数的调用就会触发返回值优化,称之为constructor arguments.
比如:

Obj a;
Obj b;
Obj c = f(a, b);

这里会将return 表达式定义的对象直接构造于c的内存。

这里还需要再细细研究,尤其涉及到了右值引用。

条款21
利用重载避免隐式类型转换

其实没有太多说的,比如前面,将char * 传递给 const string&. 会产生临时对象,这里就是说重载函数,使其有一个char* 参数的版本,就不会有临时对象了。
需要注意的是,这里提到,如果是重载运算符,至少要求有一个类型是用户自定义类型,想想是合理的,你不可以去重载两个int的加法,那样确实就诡异了。

条款22
考虑以操作符符合形式(op=) 取代独身形式(op)

主要就是说, 独身版本会产生临时对象,

Obj a , b, c;
Obj res = a + b + c;

这里就会产生2个临时对象,不过在c++11中这个问题好像没有了,需要去看下。

条款23
考虑使用其他程序库

作者举了个例子,说iostream 比printf系列要慢,好像在哪看过,是因为同步还是上面的,所以如果你的瓶颈在IO,就需要考虑替换,如果瓶颈在内存分配,就需要考虑换一个内存管理器。

条款24
了解虚函数,多继承,RTTI的成本。

这里作者说的简单了,比较浅,多重继承少见,我也不是很明白。主要是虚函数了,其实就是
(pObj->vptr[i])(this);
常见的虚函数调用,真正的形式一般是这样。
RTTI一般是在虚函数表的第一项,记录了type info.
有虚函数的RTTI,是运行时的机制,没有虚函数的时编译时的机制,对于有虚函数的对象,指针和对象的RTTI可能时(typeid)可能是不同的。
虚函数可以是inline吗,一般而言,inline的虚函数没有意义,我不确定编译器能否允许。因为虚函数本质就是函数指针,当你写好一个虚函数调用时,真正的对象可能都还没有被产生,虚函数是一种动态绑定,inline是编译时的一种手段,所以一般而言没有意义。不过对于对象调用虚函数,可能有点意义了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值