有人可以解释这个模板代码,它给我一个数组的大小?

mar*_*l0x 62 c++ arrays size templates

template<typename T, size_t n>
size_t array_size(const T (&)[n])
{
    return n;
}
Run Code Online (Sandbox Code Playgroud)

我没有得到的部分是这个模板函数的参数.当我通过数组时,数组会发生什么,它给出n了数组中元素的数量?

Joh*_*itb 90

好吧,首先你必须明白,试图从数组中获取一个值可以给你一个指向它的第一个元素的指针:

int a[] = {1, 2, 3};
int *ap = a; // a pointer, size is lost
int (&ar)[3] = a; // a reference to the array, size is not lost
Run Code Online (Sandbox Code Playgroud)

引用引用使用其确切类型或基类类型的对象.关键是模板通过引用获取数组.C++中不存在作为参数的数组(不是对它们的引用).如果为参数提供数组类型,则它将是指针.因此,当我们想知道传递的数组的大小时,使用引用是必要的.自动推导出大小和元素类型,通常是函数模板的情况.以下模板

template<typename T, size_t n>
size_t array_size(const T (&)[n]) {
    return n;
}
Run Code Online (Sandbox Code Playgroud)

使用我们之前定义的数组调用a将隐式实例化以下函数:

size_t array_size(const int (&)[3]) {
    return 3;
}
Run Code Online (Sandbox Code Playgroud)

哪个可以这样使用:

size_t size_of_a = array_size(a);
Run Code Online (Sandbox Code Playgroud)

还有我前一段时间由一个变化[编辑:原来已经有人有这样相同的想法在这里 ]可以在编译期确定的值.它不是直接返回值,而是根据以下内容为模板提供返回类型n:

template<typename T, size_t n>
char (& array_size(const T (&)[n]) )[n];
Run Code Online (Sandbox Code Playgroud)

你说如果数组有n元素,返回类型是对具有大小n和元素类型的数组的引用char.现在,您可以获得传递数组的编译时确定大小:

size_t size_of_a = sizeof(array_size(a));
Run Code Online (Sandbox Code Playgroud)

因为char具有n元素的数组具有sizeof n,所以也将给出给定数组中元素的数量.在编译时,你可以做到

int havingSameSize[sizeof(array_size(a))];
Run Code Online (Sandbox Code Playgroud)

因为函数永远不会被实际调用,所以不需要定义它,因此它没有实体.希望我能稍微澄清一下这个问题.

  • 使用C++ 11的`constexpr`,'return n;' 函数成为编译时常量!`template <typename T,size_t n> constexpr size_t array_size(const T(&)[n]){return n; }` (18认同)

Ecl*_*pse 21

可以这样想,假设你有一堆功能:

// Note that you don't need to name the array, since you don't
// actually reference the parameter at all.
size_t array_size(const int (&)[1])
{
    return 1;
}

size_t array_size(const int (&)[2])
{
    return 2;
}

size_t array_size(const int (&)[3])
{
    return 3;
}
// etc...
Run Code Online (Sandbox Code Playgroud)

现在当你调用它时,会调用哪个函数?

int a[2];
array_size(a);  
Run Code Online (Sandbox Code Playgroud)

现在,如果你对数组化进行模板化,你会得到:

template <int n>
size_t array_size(const int (&)[n])
{
    return n;
}
Run Code Online (Sandbox Code Playgroud)

编译器将尝试实例化array_size的一个版本,该版本匹配您调用它的任何参数.因此,如果使用10个int的数组调用它,它将实例化array_size,其中n = 10.

接下来,只是模板化类型,因此您可以使用不仅仅是int数组来调用它:

template <typename T, int n>
size_t array_size(const T (&)[n])
{
    return n;
}
Run Code Online (Sandbox Code Playgroud)

而且你已经完成了.

编辑:有关的说明(&)

需要括号&来区分int引用数组(非法)和引用int数组(你想要的).由于优先级[]高于&,如果你有声明:

const int &a[1];
Run Code Online (Sandbox Code Playgroud)

由于运算符优先级,最终会得到一个对int引用的单元素数组.如果你想&先应用,你需要用括号强制它:

const int (&a)[1];  
Run Code Online (Sandbox Code Playgroud)

现在你有了一个int元素数组的const引用.在函数参数列表中,如果不使用参数名称,则无需指定参数名称,因此可以删除名称,但保留括号:

size_t array_size(const int (&)[1])
Run Code Online (Sandbox Code Playgroud)

  • 在这两种情况下,您实际上都需要括号. (2认同)