临时变量连连看~~
string FindAddr( list<Employee> emps/*传入非引用参数*/,
string name/*同上*/ )
{
for( list<Employee>::iterator i = emps.begin();
i != emps.end();//书上建议将这个改为存储end()的位置,提升性能,但是这个要综合考虑!,下面详细叙述
i++ /*后置的自增会产生临时对象*/)
{
if( *i == name )//擦!这个实在太隐含了。。。隐式转换造成的临时变量!
{
return i->addr;
}
}
return "";//返回也会产生一个临时的变量
}
- 使用const 引用而非传值;
- 如果有可能,尽量使用前置自增(在某些需求下必须使用后置的时候再使用后置的自增);
- 显示的使用构造函数;
- Prefer precomputing values that won't change, instead of recreating objects unnecessarily,这个是书上的原话,但是笔者个人认为,对于这种情况,需要慎重选择:如果可以确定不会对容器做任何的导致迭代器失效的操作,这么做没有问题;但是如果有操作导致迭代器失效,那么,这个所谓的效率提升将成为一个bug。。。综上所述,还是不用的好。。。
连连看结束,下一个问题:
string FindAddr( const list<Employee>& emps,
const string& name )
{
list<Employee>::const_iterator end( emps.end() );
for( list<Employee>::const_iterator i = emps.begin();
i != end;
++i )
{
if( i->name == name )
{
return i->addr;
}
}
return "";
}
还是这个稍微改进版本的问题,如何使用通用算法改进?该函数实现的其实是一个查找的任务,顺序遍历,find可以做的更好~
so,使用find代替循环查找部分,可以得到较好的结果~
编译器何时优化后置的自增操作符?
对于内置类型,编译器会做优化,但是对于类类型,编译器不会自动的优化,除非:
There is a way you can deliberately let the compiler see the relationship between pre- and postincrement for a class type: Implement the canonical form of postincrement, which calls preincrement, and declare it
inline so that the compiler can see across the function-call boundary (if it respects the
inline directive) and detect the unused temporary object.
自己实现后置操作符,并且将其声明为inline,致使编译器能够看见(但是,是否被inline谁说了算,你懂得);
老生常谈的失效问题:
任何insert和push操作都可能导致迭代器失效(容器可能空间不够,另外申请空间并执行了拷贝);
erase、pop_front、pop_back会使指向被删除元素的所有迭代器失效;
对于vector容器,指向删除点后面的元素迭代器通常也会失效;
对于deque容器,如果删除时不包含第一个或者最后一个元素,那么该deque容器相关的所有迭代器都会失效;
resize可能使迭代器失效,在vector和deque上做resize可会使所有的迭代器失效;
赋值和assign使左操作数容器的所有迭代器失效;