【问题标题】:How does this "size of array" template function work? [duplicate]这个“数组大小”模板函数是如何工作的? [复制]
【发布时间】:2011-03-23 02:01:51
【问题描述】:

有人能解释一下这段代码是如何工作的吗?我知道这段代码的目的是获取数组的长度,但是不知道这段代码是怎么工作的:

template<typename T, int size>
int GetArrLength(T(&)[size]){return size;}

【问题讨论】:

  • @thyrgle:这比sizeof 有一个优势,如果你不小心给它一个指针而不是一个数组,它将无法编译。
  • @litb:除了“普遍感到恼火”之外,没有寻找重复项的动机。与重新回答问题相比,搜索重复并投票结束通常需要更长的时间,并且即使您有新问题与其重复的问题的最佳答案。叹息。

标签: c++ arrays templates size sizeof


【解决方案1】:

首先让我们剖析参数T(&amp;)[size]。首先从内到外、从右到左、括号组读取声明:它是一个未命名的参数,它是对大小为 size、类型为 T 的数组的引用。

也就是说,它接受对任何数组的引用,其中数组的类型和大小都是模板参数。

如果我们这样称呼它:

int a[10];
GetArrLength(a);

编译器会尝试推断模板参数。要使参数类型与您传递的内容相匹配,T 必须是 intsize 必须是 10(使参数成为对 10 个 ints 的数组的引用)。

然后您返回该大小,为您提供数组中元素的数量。


这段代码有两个“问题”。首先,sizes 不能为负数,因此使用有符号类型作为模板参数和返回类型是没有意义的。相反,应该使用无符号类型;最好是std::size_t:

template<typename T, std::size_t Size>
std::size_t GetArrLength(T(&)[Size]) { return size; }

第二个是这个函数的结果不是一个常量表达式,即使一个数组的大小是。虽然这在大多数情况下都很好,但如果我们能从中得到一个常量表达式会更好。这就是你最终得到这个解决方案的地方:

template <std::size_t N>
struct type_of_size
{
    typedef char type[N];
};

template <typename T, std::size_t Size>
typename type_of_size<Size>::type& sizeof_array_helper(T(&)[Size]);

#define sizeof_array(pArray) sizeof(sizeof_array_helper(pArray))

这样使用:

int a[10];
const std::size_t n = sizeof_array(a); // constant-expression!

它通过三件事起作用:第一件事与上面的想法相同,模板参数将被填写给你数组的大小。

第二部分是使用该信息来制作具有特定大小的类型,因此是 type_of_size 帮助器。这部分不是绝对必要的,但我认为它使代码更易于阅读。 char[N] 的大小总是等于 N,因此我们可以滥用它来“存储”数组的大小...以 type 本身的大小!

第三部分是使用sizeof 获得该大小。它实际上并不评估任何东西,所以我们不需要函数的定义。它只是说“如果你这样做......大小将......”。大小是我们“存储”的大小,在 char 数组中。

【讨论】:

  • 但如果我将代码更改为 T&[size] 它将不起作用,为什么? (&) 和 only & 有什么区别谢谢
  • T&[size] 是一个引用数组。你想要一个数组的引用。
  • 您可以在最后一个版本中跳过样板代码,但会以可读性为代价,但我将其作为@Matthew Flaschen 和@BobAlmond 的练习:) template &lt;typename T, size_t size&gt; char (&amp;sizeof_array_helper( T (&amp;)[size]))[size]; - 宏将是保持原样。
  • 使用 C++11 的 constexpr,'return n;'函数成为编译时间常数! template &lt;typename T, size_t n&gt; constexpr size_t array_size(const T (&amp;)[n]) { return n; }
  • @user666412:你的输入不安全:int* i = ...; sizeof_array(i) /* should not compile */
猜你喜欢
  • 2011-09-16
  • 2014-08-01
  • 2020-02-20
  • 1970-01-01
  • 1970-01-01
  • 2011-01-23
  • 2021-03-15
  • 1970-01-01
  • 2020-03-09
相关资源
最近更新 更多