这在最近的代码审查讨论中提出,但没有令人满意的结论。有问题的类型类似于 C++ string_view TS。它们是围绕指针和长度的简单非拥有包装器,装饰有一些自定义函数:
#include <cstddef>
class foo_view {
public:
foo_view(const char* data, std::size_t len)
: _data(data)
, _len(len) {
}
// member functions related to viewing the 'foo' pointed to by '_data'.
private:
const char* _data;
std::size_t _len;
};
出现的问题是,是否有一个论点是更喜欢通过值或 const 引用传递此类 View 类型(包括即将到来的 string_view 和 array_view 类型)。
支持按值传递的论点相当于“减少输入”、“如果 View 具有有意义的突变,则可以改变本地拷贝”和“可能不会降低效率”。
支持通过 const 引用传递的论点相当于“通过 const& 传递对象更惯用”,并且“可能效率不低”。
在通过值还是通过 const 引用传递惯用 View 类型是否更好方面,是否有任何其他考虑可能会最终以一种或另一种方式摇摆论点。
对于这个问题,假设 C++11 或 C++14 语义,以及足够现代的工具链和目标架构等是安全的。
最佳答案
如有疑问,请按值传递。
现在,您应该很少有疑问。
传递值通常代价高昂,而且 yield 甚微。有时,您实际上想要对存储在其他地方的可能变异值的引用。通常,在通用代码中,您不知道复制是否是一项昂贵的操作,因此您宁可不这样做。
在有疑问时应该按值传递的原因是因为值更容易推理。当您调用函数回调或您拥有的东西时,对外部数据的引用(甚至是 const
之一)可能会在算法中间发生变化,从而将看似简单的函数渲染成复杂的困惑。
在这种情况下,您已经有一个隐式引用绑定(bind)(到您正在查看的容器的内容)。添加另一个隐式引用绑定(bind)(到查看容器的 View 对象)同样糟糕,因为已经存在复杂性。
最后,编译器对值的推理比对值的引用更好。如果您离开本地分析的范围(通过函数指针回调),编译器必须假定存储在 const 引用中的值可能已经完全改变(如果不能证明相反的话)。可以假定自动存储中的值没有人指向它的指针不会以类似的方式进行修改——没有定义的方式来访问它并从外部范围更改它,因此可以假定这种修改不会发生.
当您有机会将值作为值传递时,请拥抱简单性。它只是很少发生。
关于C++ View 类型 : pass by const& or by value?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27256377/