通常我们认为,传值和传常引用在效果上是一致的,例如:
对自定义类 struct node;
,定义小于运算符
写成bool operator<(node a,node)
与bool operator<(const node&a,const node&b)
算法逻辑是不受影响的,都可以正确地用sort排序。
两者唯一的差距在于时间常数:前者需要O(sizeof(node)),后者仅需要O(void*)。
这是因为发生传值调用时,将值拷贝了一份保存在栈或寄存器中;
而发生传常引用调用时,拷贝的是变量的内存地址,以直接访问变量的值,const
限制了该变量只读,无法直接被修改。
但是,若在函数中,变量可以其他途径被修改(如传入另一指针或引用),当上述情况发生时,
通过常引用访问的变量值已被修改,这可能导致算法逻辑上的错误,无法得到正确的答案。
一个典型的错误是:
struct node{
int first,second;
void update(const node&a,const node&b){
first=max(a.first,b.first);
second=max(min(a.first,b.first),max(a.second,b.second));
}
}
该样例实现了一个保存最大与次大值的类型,但是,成员函数隐式地通过this
修改了*this
的值,
若b
与this
对应的变量是同一个,且它的first值被另一变量更新,就会发生错误。
在设计算法时,应考虑到这一细节,避免不必要的错误。
听君一席话,如胜一席话