是 t min(t, t);总是比 const T&Min(const T&, const T&);如果 sizeof(T) <= sizeof(void*)?

Is T Min(T, T); always better than const T& Min(const T&, const T&); if sizeof(T) <= sizeof(void*)?

本文关键字:const sizeof void lt Min min 如果      更新时间:2023-10-16
template<class T>
T Min(T a, T b)
{
return a < b ? a : b;
}
template<class T>
const T& Min(const &T a, const T& b)
{
return a < b ? a : b;
}

哪个更好?或者,我应该重新定义模板函数如下:

template<class T, ENABLE_IF(sizeof(T) <= sizeof(void*))>
T Min(T a, T b)
{
return a < b ? a : b;
}
template<class T, ENABLE_IF(sizeof(T) > sizeof(void*))>
const T& Min(const &T a, const T& b)
{
return a < b ? a : b;
}
// Note: ENABLE_IF is a helper macro.

我不能肯定,但考虑到

template<class T>
const T& Min(const &T a, const T& b)
{
return a < b ? a : b;
}

基本上被替换为(比如T=bool):

const bool & Min(const bool & a, const bool & b)
{
return a < b ? a : b;
}

我想说,这是一个公平的假设,编译器将以最有效的方式传递布尔。I.E,只是因为我们使用&这并不意味着它可以通过引用传递。

还有几个想法:当调用函数时,参数要么被推送到堆栈上,要么通过寄存器传递。

bool Min(bool a, bool b)
{
return a < b ? a : b;
}

会比"更好"/"更快">

const bool & Min(const bool & a, const bool & b)
{
return a < b ? a : b;
}

如果传递bool比传递const bool &快(在函数开始时忽略解引用)。我看不出这是真的,因为除非它被推送到堆栈上(取决于您的调用约定),否则寄存器在主机体系结构上都至少有指针大小。(I.E,rax为64位,eax为32位)

此外,我认为编译器内联会更容易,因为(仅从函数签名)我们可以保证函数永远不会局部修改ab的值,因此不需要它们的空间。

对于用户定义的类型,有两种情况。

  1. 类型适合寄存器,我们可以像对待基本类型一样对待它
  2. 该类型不适合寄存器,必须通过引用传递(如果使用const & T)或作为副本传递(如果仅使用T)。由于复制类会调用类构造函数,因此const & T在任何情况下都可能更快

但是,我真的只是在这里猜测。要检查boolconst bool &是否有差异,最好的方法是通过输出程序集并查看是否有任何差异来检查特定的编译器。

HTH。

我看到g++在优化时会自动执行这一操作:它可以生成一个按值接受参数的Min版本,当它可以判断这更有效并且不会违反规则时(我认为这基本上意味着具有琐碎复制构造函数的小类型)。

我不知道这个优化的名字是什么,也不知道其他编译器是否实现了它。


顺便说一句,我想知道你是否能在C++11:中两全其美

template <typename T, typename U>
constexpr auto Min(T&& l, U&& r) -> decltype(l < r ? l : r)
{
return l < r ? l : r;
}

如果我对"通用引用"的理解是正确的,那么它的效率永远不会低于在您的示例中使用左值引用,并且如果lr是右值(例如整数文本),则可能更高效。作为额外的奖励,你可以在有意义的地方比较不同类型的东西(intlong或其他什么)。