在 C++ 中通过值传递还是通过引用传递到 const 更好?
我想知道哪个是更好的做法。我意识到通过引用传递到 const 应该在程序中提供更好的性能,因为您没有制作变量的副本。
原文由 Matt Pascoe 发布,翻译遵循 CC BY-SA 4.0 许可协议
在 C++ 中通过值传递还是通过引用传递到 const 更好?
我想知道哪个是更好的做法。我意识到通过引用传递到 const 应该在程序中提供更好的性能,因为您没有制作变量的副本。
原文由 Matt Pascoe 发布,翻译遵循 CC BY-SA 4.0 许可协议
3 回答2k 阅读✓ 已解决
2 回答3.9k 阅读✓ 已解决
2 回答3.2k 阅读✓ 已解决
1 回答3.2k 阅读✓ 已解决
1 回答2.7k 阅读✓ 已解决
3 回答3.4k 阅读
1 回答1.6k 阅读✓ 已解决
通常建议最佳实践1 对 所有类型 使用 pass by const ref,除了内置类型(
char
,int
,double
,等等2。 ),用于迭代器和函数对象(lambdas,派生自std::*_function
的类)。在 移动语义 存在之前尤其如此。原因很简单:如果您按值传递,则必须制作对象的副本,并且除了非常小的对象外,这总是比传递引用更昂贵。
使用 C++11,我们获得了 移动语义。简而言之,移动语义允许在某些情况下,一个对象可以“按值”传递而不复制它。特别是,当您传递的对象是 rvalue 时,就是这种情况。
就其本身而言,移动对象仍然至少与通过引用传递一样昂贵。然而,在许多情况下,一个函数无论如何都会在内部复制一个对象——即它将获得参数的 _所有权_。 2
在这些情况下,我们有以下(简化的)权衡:
“按值传递”仍然会导致对象被复制,除非对象是右值。在右值的情况下,可以移动对象,因此第二种情况突然不再是“复制,然后移动”,而是“移动,然后(可能)再次移动”。
对于实现正确移动构造函数的大型对象(例如向量、字符串……),第二种情况比第 一种 更有效。因此, 如果函数拥有参数的所有权,并且对象类型支持高效移动,则建议使用按值传递。
历史注释:
事实上,任何现代编译器都应该能够找出何时按值传递代价高昂,并尽可能隐式地将调用转换为使用 const ref。
理论上。 在实践中,编译器不能总是在不破坏函数的二进制接口的情况下改变它。在某些特殊情况下(当函数被内联时),如果编译器能够确定原始对象不会通过函数中的操作进行更改,则实际上会省略副本。
但总的来说,编译器无法确定这一点,而 C++ 中移动语义的出现使这种优化的相关性大大降低。
1例如,Scott Meyers, Effective C++ 。
2对于对象构造函数来说尤其如此,它可以接受参数并将它们存储在内部,作为构造对象状态的一部分。