参数传递礼仪 (C++) 恒量与值
Parameter Passing Etiquette (C++) const& vs. value
如果函数需要与参数相关的只是查看其值,那么是否应该始终通过常量引用传递该参数?
我的一位同事说小类型无关紧要,但我不同意。
那么这样做有什么好处吗:
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;
}
但我不知道是否总是如此。
我相信我是对的,因为它不会产生任何额外的开销,而且它是自我记录的。
但是,我想问社区我的推理和假设是否正确?
你的同事是对的。对于小型类型(char,int),当不修改变量时,通过引用传递是没有意义的。按值传递会更好,因为指针的大小(用于通过引用传递的情况)大约是小类型的大小。
此外,按值传递,打字较少,可读性略高。
即使sizeof(chref)
与sizeof(ch)
相同,在大多数系统上,逐个引用传递字符确实会占用更多的字节:尽管该标准没有说明引用的实现的任何具体内容,但地址(即指针)经常在幕后传递。启用优化后,这可能无关紧要。对模板函数进行编码时,不会修改的未知类型的项应始终通过 const 引用传递。
就小类型而言,您可以使用const
限定符按值传递它们,以强调您不会通过函数的签名接触参数的观点:
void function(const char ch){ //<- value
if (ch == 'a'){
DoSomething(ch);
}
return;
}
对于较小的值,创建引用并取消引用的成本可能大于复制它的成本(如果存在差异)。当您考虑到引用参数几乎总是作为指针实现时,尤其如此。如果您只是将值声明为 const
,则两者都可以很好地记录(我仅将此值用于输入,它不会被修改)。我通常只是按值const
所有标准内置类型,并将所有用户定义的/STL类型作为const &
。
您的sizeof
示例存在缺陷chref
因为它只是ch
的别名。对于任何类型的T
,您都会获得相同的sizeof(T)
结果。
通过的大小不同。结果取决于 ABI 调用约定,但sizeof(referenceVariable)
会产生sizeof(value)
。
如果函数需要与参数相关的只是查看其值,那么是否应该始终通过常量引用传递该参数?
这就是我所做的。我知道人们不同意我的观点,并主张按值传递小内置,或者更喜欢省略const
。通过引用传递可以添加指令和/或占用更多空间。我传递这种方式是为了保持一致性,并且因为始终衡量任何给定平台的最佳通过方式维护起来很麻烦。
除了可读性之外,没有其他优势(如果这是您的偏好)。性能可能会受到非常轻微的影响,但在大多数情况下,这不会是一个考虑因素。
按值传递这些小内置更常见。如果按值传递,则可以const
限定定义(独立于声明)。
我的建议是,绝大多数团队应该简单地选择一种方式来通过并坚持下去,除非每个指令都很重要,否则性能不应该影响这一点。const
从不受伤。
在我看来,您通过 const 引用传递的一般方法是一个很好的做法(但请参阅下文,了解您的示例的一些警告)。另一方面,您的朋友是正确的,对于内置类型,通过引用传递不会导致任何显着的性能提升,甚至可能导致边际性能损失。我来自 C 背景,所以我倾向于根据指针来考虑引用(即使存在一些细微的差异),并且在我熟悉的任何平台上,"char*"都会比"char"大。
[编辑:删除了不正确的信息。
在我看来,底线是,当你传递更大的用户定义类型时,被调用的函数只需要读取值而不修改它们,通过"type const&"传递是一个很好的做法。正如您所说,它是自我记录的,有助于阐明内部 API 各个部分的角色。
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 使用指向成员的指针将成员函数作为参数传递
- 如何将参数传递给正在使用模板的类
- 是否有C++编译器选项允许激进地删除所有函数调用,并将参数传递给具有空体的函数
- 修改函数中的指针(将另一个指针作为参数传递)
- 如何将部分流作为参数传递
- 我正在开发服务器,ip作为参数传递不起作用
- 将成员函数指针作为参数传递给模板方法
- 如何在C++中将迭代器作为函数参数传递
- 将附加参数传递给使用 beast::bind_front_handler 调用的函数
- 如何将一个类的函数作为另一个类的另一个函数的参数传递
- 将参数传递为"const"的奇怪效果
- 如何在 c++ 中将函数作为参数传递?
- 在 C++ 中将非指定类型作为参数传递的最佳方法?
- 使用引用与指针将数组作为参数传递
- 如何将成员函数作为回调参数传递给需要"typedef-ed"自由函数指针的函数?
- 将参数打包的参数传递到 std::queue 中,以便稍后使用不同的函数调用
- 为什么我不能将引用作为 std::async 的函数参数传递
- 如何在不使用指针的情况下将派生类的对象作为参数传递给基类中的函数?
- 将__device__ lambda 作为参数传递给 __global__ 函数