2012-04-21 21 views
3

如果所有函数需要做的一个参数是看它的价值与价值,不应该你总是擦肩而过不断引用该参数?参数传递礼仪(C++)const的&

我的一位同事说,它不小的类型无所谓,但我不同意。

那么,有没有优势,做到这一点:

void function(char const& ch){ //<- const ref 
    if (ch == 'a'){ 
     DoSomething(ch); 
    } 
    return; 
} 

在此:

void function(char ch){ //<- value 
    if (ch == 'a'){ 
     DoSomething(ch); 
    } 
    return; 
} 

他们似乎是相同的大小对我说:

#include <iostream> 
#include <cstdlib> 

int main(){ 

    char ch; 
    char& chref = ch; 

    std::cout << sizeof(ch) << std::endl; //1 
    std::cout << sizeof(chref) << std::endl; //1 

    return EXIT_SUCCESS; 
} 

但我不知道这是否总是如此。
我相信我是正确的,因为它不会产生任何额外的开销,这是自我记录。
但是,我想问问社区我的推理和假设是否正确?

+1

你的演示代码似乎表明'sizeof(ch)'和'sizeof(ch)'是一样的 - 是你想要的吗? – 2012-04-21 04:07:38

+1

即使你的意思是'sizeof(chref)'为其中之一,你仍然会得到相同的大小。但是这并不相关,因为当你做'sizeof(chref)'时,它实际上告诉你ch的大小。一旦你初始化了一个引用,它的所有操作就好像他们实际上是在引用上完成的一样。但是这并没有告诉你任何关于编译器的魔法,可能会在幕后进行。 – 2012-04-21 04:10:40

+0

@JonathanLeffler修复 – 2012-04-21 04:23:43

回答

2

即使sizeof(chref)相同sizeof(ch),通过参考确实需要在大多数系统上更多的字节传送字符:虽然标准没有说具体的关于引用的实施,一个地址(即指针)什么是定期通过在幕后。通过优化,它可能无所谓。当您编写模板函数时,不会被修改的未知类型的项目应该始终由const引用传递。

至于小类型去,你可以通过值与const预选赛通过他们强调的是,你是不是要通过你的函数的签名触摸争论点:

void function(const char ch){ //<- value 
    if (ch == 'a'){ 
     DoSomething(ch); 
    } 
    return; 
} 
1

的大小是不是与通过相同。结果取决于ABIs调用约定,但sizeof(referenceVariable)产生sizeof(value)

如果一个函数需要处理一个参数是看它的值,你不应该总是通过常量引用传递该参数吗?

这就是做的。我知道人们不同意我的观点,主张通过价值传递小建筑物,或者宁愿忽略const。按引用传递可以添加指令和/或消耗更多空间。我通过这种方式一致性,因为总是测量的最佳方式来传递任何给定的平台是很多的麻烦来维持的。

没有超出可读性优势(如果这是你的偏好)。性能可能会受到很小的影响,但在大多数情况下不会考虑。

由值传递这些小建宏是比较常见的。如果按价值传递,则可以const限定定义(独立于声明)。

我的建议是,绝大多数团队应该简单地选择一种方式来通过并坚持下去,除非每条指令都计数,否则性能不应该影响。 const永远不会伤害。

+1

是的。在(*)极不可能的事件中,(a)你的程序不够快,(b)“不够快”和“足够快”之间的差异是通过引用,那么你可以重新访问它。在这种情况发生之前,最好尽可能传达你的意图。 – Ben 2012-04-21 04:19:24

+0

@绝对+1。我曾经在一些体系结构上对它进行了测量,并得出结论认为,在我不愿下降到组装的高度优化的性能关键程序中,差异并不显着。 – justin 2012-04-21 04:23:12

0

在我看来,通过const引用传递的一般方法是一种很好的做法(但请参阅下面的示例中的一些注意事项)。另一方面,你的朋友是正确的,对于内置类型,通过引用不应该导致任何显着的性能增益,甚至可能导致边际性能损失。我来自C背景,所以我倾向于在指针方面考虑引用(尽管存在一些细微的差异),并且在任何平台上,“char *”将比任何平台上的“char”更大熟悉。

[编辑:删除不正确的信息]

底线,在我看来,就是当你传递较大的用户定义类型,并调用函数只需要在不修改他们读值,通过“类型const &”是一个好习惯。正如你所说,它是自我记录,并有助于澄清各种内部API的角色。

+1

不存在'const char const&'这样的事情。 'const'绑定到左边的值,除非它是第一个单词,在这种情况下,它绑定到右边的值。所以你说的是'char const const'。'char const&'大致等价于'char const * const',这意味着一个'const T&'''T const&'(同样的东西)不能修改这个值。 – 2012-04-21 04:31:00

+0

你是对的。我必须在C++中处理这个问题已经有好几年了。这可能会编译IIRC,但它确实是多余的。感谢您的澄清。我认为我最近在C中使用指针的工作让我失望了。 – coydog 2012-04-21 04:35:51

+2

@coydog:如果它是错误的,你应该编辑你的文章*删除*的信息,而不是简单地说不管它。 – 2012-04-21 04:50:27

2

对于较小的值,创建引用和取消引用的成本很可能大于拷贝它的成本(如果根本不同的话)。当您认为参考参数几乎总是作为指针实现时,尤其如此。如果您只是将您的值声明为const(我仅将该值用于输入并且不会被修改),那么这两个文档同样适用。我通常只将const值和所有用户定义/ STL类型的所有标准内置类型制作为const &

您的sizeof示例存在缺陷,因为chref只是ch的别名。 sizeof(T)对于任何类型的T都会得到相同的结果。

3

你的同事是正确的。对于小类型(char,int),当变量不被修改时,通过引用传递是没有意义的。按值传递会更好,因为指针的大小(在通过引用传递的情况下使用)大约是小类型的大小。

此外,通过价值传递,键入较少,并且可读性略高。