应该将C ++中大多数/所有设置器函数的参数编写为const引用吗?

时间:2018-10-03 22:54:54

标签: c++ setter

例如

    void SetNumbers(const double& a, const double& b)
      {
        m_a = a;
        m_b = b
      }

不只是

void SetNumbers(double a, double b) 
  {
        m_a = a;
        m_b = b
  }

我听说它更快,更安全,也许还有其他优点

2 个答案:

答案 0 :(得分:0)

这取决于参数类型。

如果值的大小为<= sizeof(void*),例如intfloat(通常是double),则最好按值传递它很有可能会放入寄存器中,而不是在内存中查找。

如果它是一个大对象(如数组或字符串),则打算从其中复制数据,最好将其用作const &(常量引用)。如果您要移动或使用输入,最好将其作为&&(右值引用)接收。

答案 1 :(得分:0)

在关联类型的复制/移动运算符很简单的情况下,这两种方法并不等效。

假设您不在乎这种区别(即,包括任何复制/移动在内的整个函数调用的效果在两种情况下都是相同的),那么通常它取决于ABI的机械细节:< / p>

  • 小型类型通常可以在单个寄存器中有效地传递。在这种情况下,由于该副本在ABI中是隐式的,所以没有按值传递开销。
  • 即使在“按值传递”时,也不能通过寄存器传递不能通过寄存器的较大类型,这意味着您在按值传递的情况下会产生一个副本。
  • 但是,如果内联函数,则此副本可能会消失,因为编译器可以看到该副本从未被访问过。
  • 按值传递可确保参数不能使用 alias ,这可以帮助更有效地优化函数,并且这种效果有时会非常大(可以使用扩展名,例如__restrict以获得与参考相同的效果。
  • 内联可以再次“否定”上述优势。

不幸的是,没有简单的答案。

仅考虑性能,合理的启发式方法可能是:

对于要在重要平台上的寄存器中传递的类型,建议使用按值传递。如果您不知道哪种类型将按值传递,则可以假定仅原始类型按值传递(但这通常是一种悲观的假设)。

对于较大的类型(在您的示例中进行复制),对于C ++ 11和更高版本,可能仍然更喜欢传递值,因为您可以std::move赋值中的参数,对于具有可移动类型的参数,在使用右值调用函数时,其效率通常相似。对于不可移动类型或当参数不是右值时,两种方法的效率相似。

对于不制作副本的较大类型,我建议通过const引用传递,除非在极少数情况下您无法避免混淆问题,在这种情况下需要副本。

>