2011-07-22 78 views
13

是否有任何理由不发送参数作为const &而不是按值,当它不会被更改并且不会进行复制?我的理解是const by value参数与没有const(并且不会相互重载)相同,因此它仍将被复制。作为Const参考的函数参数

我知道最好通过const &发送大对象,但我不知道这条线是在哪里。或者如果即使很小的参数应该通过值发送,如果它们将不会被更改或复制。

注意::我试图寻找这个,但主题是相当含糊,所以我没有找到任何好的答案,我很抱歉如果这已被回答(发现许多问题什么时候使用const何时使用const &但不关于价值的优势vs const &对于不明显的对象)。

+2

你可能会觉得这篇文章有意思:http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ – lccarrasco

+0

完全型我一直在寻找的东西,谢谢!关键字如此一般,我很难搜索。 –

+0

@lccarrasco:Dave Abrahams正在讨论通过函数内的值来返回对象。问题是关于函数的输入参数。在这种情况下,OP应该通过const引用传递本机类型以外的对象。 – Praetorian

回答

22

将只读参数作为常量引用传递并且对于任何类型的重量级类肯定是最有效的方法。但是,您可能想考虑通过复制传递基元类型,因为在那里使引用可能实际上比仅复制引起更多的成本(例如,复制只适合一个寄存器,而引用可能用一个指针等)。

此外,你可能通过std::shared_ptr和迭代器的价值,他们是为此。

至于通过常量值,这是一个执行细节。使用这样的:

// Declaration: 
int foo(int n, double d); // No "const"! Constness is not part of the interface. 

// Definition 
int foo(int n, const double d) // implementation detail 
{ 
    while (n--) { if (d > n) return n; } 
} 

在实现中,你可能会或可能不会选择直接使用参数变量,并对其进行修改(如n),或者你可以选择把它们看作是只读(如d ),并且适当地声明参数。

+2

我没有想到指针复制对原始类型来说同样昂贵或者更差,谢谢。 –

+7

值得指出的是,如果你通过一个线程边界引用一个引用计数句柄(比如'shared_ptr'),那么它就变成**不可能安全地减少引用计数** - 你有*要传递在这种情况下的价值。 – spraff

+0

@spraff:不错。 –

12

作为一个经验法则,你应该通过原语类型,如指针,intboolfloatdouble通过(非const)值,和对象类型如std::stringstd::vector和自定义类由(常数)参考。作为这个规则的一个例外,有一些轻量级的类被专门设计用来传递值,比如智能指针。

通过const值传递一个值,例如, void foo(const double bar),是没有意义的 - 为什么不应该允许foo修改其bar的副本?将参数声明为const在这里没有用处。

通过引用传递基元也没什么意义。在幕后,当一个参数通过引用传递时,一个指针是按值传递的。复制指针通常与复制基本类型(例如int)一样昂贵,而对于大多数C++程序员来说,const int&类型的参数看起来很奇怪。

+0

如果可以的话,我会接受两个答案! –

+3

有些人(我不在其中),他们更喜欢'const double bar'。他们说它通过覆盖函数中参数的值来防止错误原因。 –

+0

只需添加到@larsmans的评论,使用'const double bar'可以防止您意外地使用'if(bar = 5)'而不是'=='。但是这样做的代价是限制你可以用'bar'做什么。出于某种原因,您的算法可能会要求对“bar”进行原地修改。我想这仅仅是灵活性与安全性的折衷。取决于你想信任下一位程序员多少! –