假设我想实现一些简单的数学函数;例如,假设它是(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 );
}
但是如果它是一个模板,我看到sample implementation可能是标准将使用的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 );
}
我的问题是:
T
的简单数字类型,对const引用有什么好处吗?std::chrono
个持续时间)的类型?const&
然后一个值更好的主意功能?注意:
const&
s和其他类似数字类型时,boost::rational
可能会开始有意义;但即使这样,编译器也不会优化复制吗?答案 0 :(得分:3)
- 对于
T
这些简单的数字类型,使用const引用是否有任何好处?
没有
- 同上,对于包含单个数字作为数据成员的抽象事物(例如
std::chrono
个持续时间)的类型?
没有
- 为什么在任何相对简单的(constexpr?),无副作用的数学运算的一般情况下,取一个
const&
而不是一个值更好的想法?功能?
想象一下使用动态分配的bigint类型;复制这种类型是很昂贵的。
- 编译器不会优化复制吗?
只有当它能证明复制值没有副作用时,除非编译器看到所有涉及的代码,否则很难做到这一点。 (所以,如果你的bigint使用,比方说,GMP,你运气不好。)
答案 1 :(得分:2)
对于
T
这些简单的数字类型,获取const引用是否有任何好处?
不,我不这么认为,但也没有惩罚。
同上,对于包含单个数字作为数据成员的某些抽象事物的类型(例如
std::chrono duration
)?
同上。
为什么在一般情况下采用
const&
然后是值更好的想法(并且根本就是这样)?
标准库算法不仅适用于基本类型,还适用于用户定义的类型,复制起来可能并不便宜。对于这些类型,使用const&
可以避免复制的惩罚,同时不会损害基本类型的用法。