模板化的数学函数是否接受值或const引用

Should templated math functions take values or const references?

本文关键字:引用 const 是否 函数      更新时间:2023-10-16

假设我想实现一些简单的数学函数;例如,假设它是(c++ 17的)std::clamp的重新实现:这个函数接受一个数字,一个下界和一个上界,如果它超出了它们定义的范围,则将该数字设置为这些边界中的一个。如果它是一个具体的数字类型,比如int,我会写:

constexpr int clamp(int x, int lower_bound, int upper_bound)
{
    return x < lower_bound ? lower_bound : ( upper_bound < x ? upper_bound : x );
}

,但如果它是一个模板,我看到的样本实现可能是什么标准将使用const&的,而不是值。因此,为了使引用更简单,例如:

template <typename T>
constexpr T clip(const T& x, const T& lower_bound, const T& upper_bound)
{
    return x < lower_bound ? lower_bound : ( upper_bound < x ? upper_bound : x );
}

我的问题是:

  • 是否有任何好处采取const引用,T 's是简单的数字类型?
  • 同上,对于类型是一些抽象的东西包装单个数字作为数据成员(例如std::chrono持续时间)?
  • 为什么在任何相对简单的(constexpr?),无副作用的数学函数的一般情况下,采取const&然后一个值是一个更好的主意?

指出:

  • 我意识到当你有某种k维向量类型或boost::rational s和其他类似数字的类型时,采取const&可能开始有意义;但即使这样,编译器不会优化复制吗?
  • 不是询问任何任意的c++函数以及它是否应该按值取参数,这显然是一个坏主意。
  • 是否有任何好处采取const引用,T的是简单的数字类型?

  • 同上,对于类型是一些抽象的东西包装单个数字作为数据成员(例如std::chrono持续时间)?

  • 为什么在任何相对简单的(constexpr?),无副作用的数学函数的一般情况下,采取const&比值更好?

想象一个使用动态分配的bigint类型;复制这样的类型是很昂贵的。

    编译器不会优化复制吗?

只有当它能证明复制值没有副作用时才行,除非所有涉及的代码对编译器可见,否则很难做到这一点。(因此,如果您的bigint使用GMP,那么您就不走运了。)

对于简单的数字类型T来说,使用const引用有什么好处吗?

不,我不这么认为,但也没有惩罚。

同上,对于一些抽象的东西包装单个数字作为数据成员的类型(例如std::chrono duration)?

同上。

为什么(它是在所有)一个更好的主意采取const&然后在一般情况下的值?

标准库算法不仅为基本类型设计,也为用户定义的类型设计,复制这些类型的成本可能并不低。对于这些类型,使用const&避免了复制的惩罚,同时不影响基本类型的使用。

相关文章: