3

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

我的一位同事表示,对于小类型来说没关系,但我不同意。

那么这样做有什么好处:

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;
}

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

4

5 回答 5

3

Your colleague is correct. For small types (char, int) it makes no sense to pass by reference, when the variable is not to be modified. Passing by value would be better, as size of pointer (used in case of passing by reference) is about the size of small types.

And moreover, passing by value, is lesser typing, as well as slightly more readable.

于 2012-04-21T04:47:09.620 回答
2

尽管sizeof(chref)与 相同sizeof(ch),但在大多数系统上,按引用传递字符确实需要更多字节:尽管标准没有说明引用实现的任何具体内容,但地址(即指针)经常在幕后传递。启用优化后,这可能无关紧要。当您编写模板函数时,不会被修改的未知类型的项目应始终通过 const 引用传递。

就小类型而言,您可以使用const限定符按值传递它们,以强调您不会通过函数的签名触及参数:

void function(const char ch){ //<- value
    if (ch == 'a'){
        DoSomething(ch);
    }
    return;
}
于 2012-04-21T04:10:46.817 回答
2

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

您的sizeof示例有缺陷,因为chref它只是ch. sizeof(T)对于任何类型,您都会得到相同的结果T

于 2012-04-21T04:35:22.097 回答
1

大小与通过的一样。结果取决于 ABI 调用约定,但 sizeof(referenceVariable)生成sizeof(value).

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

这就是所做的。我知道人们不同意我的观点,并主张按值传递小型内置函数,或者更愿意省略const. 通过引用传递可以添加指令和/或消耗更多空间。我通过这种方式是为了保持一致性,因为总是衡量任何给定平台的最佳通过方式是很麻烦的维护。

除了可读性之外,没有其他优势(如果这是您的偏好)。性能可能会受到非常轻微的影响,但在大多数情况下不会考虑。

按值传递这些小内置函数更为常见。如果按值传递,您可以const限定定义(独立于声明)。

我的建议是,绝大多数团队应该简单地选择一种方式来传递并坚持下去,除非每条指令都很重要,否则性能不应影响这一点。const从来不疼。

于 2012-04-21T04:13:04.077 回答
0

在我看来,您通过 const 引用传递的一般方法是一种很好的做法(但请参阅下面关于您的示例的一些警告)。另一方面,您的朋友是正确的,对于内置类型,按引用传递不应导致任何显着的性能提升,甚至可能导致边际性能损失。我来自 C 背景,所以我倾向于根据指针来考虑引用(即使存在一些细微的差异),并且在我使用的任何平台上,“char*”都会比“char”大熟悉的。

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

在我看来,最重要的是,当您传递更大的用户定义类型,并且被调用函数只需要读取值而不修改它们时,通过“type const&”传递是一个好习惯。正如您所说,它是自我记录的,有助于阐明内部 API 各个部分的角色。

于 2012-04-21T04:27:13.070 回答