好吧,首先你必须明白,试图从数组中获取一个值可以给你一个指向它的第一个元素的指针:
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
引用引用使用其确切类型或基类类型的对象.关键是模板通过引用获取数组.C++中不存在作为参数的数组(不是对它们的引用).如果为参数提供数组类型,则它将是指针.因此,当我们想知道传递的数组的大小时,使用引用是必要的.自动推导出大小和元素类型,通常是函数模板的情况.以下模板
templatesize_t array_size(const T (&)[n]) { return n; }
使用我们之前定义的数组调用a
将隐式实例化以下函数:
size_t array_size(const int (&)[3]) { return 3; }
哪个可以这样使用:
size_t size_of_a = array_size(a);
还有我前一段时间由一个变化[编辑:原来已经有人有这样相同的想法在这里 ]可以在编译期确定的值.它不是直接返回值,而是根据以下内容为模板提供返回类型n
:
templatechar (& array_size(const T (&)[n]) )[n];
你说如果数组有n
元素,返回类型是对具有大小n
和元素类型的数组的引用char
.现在,您可以获得传递数组的编译时确定大小:
size_t size_of_a = sizeof(array_size(a));
因为char
具有n
元素的数组具有sizeof n
,所以也将给出给定数组中元素的数量.在编译时,你可以做到
int havingSameSize[sizeof(array_size(a))];
因为函数永远不会被实际调用,所以不需要定义它,因此它没有实体.希望我能稍微澄清一下这个问题.
好吧,首先你必须明白,试图从数组中获取一个值可以给你一个指向它的第一个元素的指针:
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
引用引用使用其确切类型或基类类型的对象.关键是模板通过引用获取数组.C++中不存在作为参数的数组(不是对它们的引用).如果为参数提供数组类型,则它将是指针.因此,当我们想知道传递的数组的大小时,使用引用是必要的.自动推导出大小和元素类型,通常是函数模板的情况.以下模板
templatesize_t array_size(const T (&)[n]) { return n; }
使用我们之前定义的数组调用a
将隐式实例化以下函数:
size_t array_size(const int (&)[3]) { return 3; }
哪个可以这样使用:
size_t size_of_a = array_size(a);
还有我前一段时间由一个变化[编辑:原来已经有人有这样相同的想法在这里 ]可以在编译期确定的值.它不是直接返回值,而是根据以下内容为模板提供返回类型n
:
templatechar (& array_size(const T (&)[n]) )[n];
你说如果数组有n
元素,返回类型是对具有大小n
和元素类型的数组的引用char
.现在,您可以获得传递数组的编译时确定大小:
size_t size_of_a = sizeof(array_size(a));
因为char
具有n
元素的数组具有sizeof n
,所以也将给出给定数组中元素的数量.在编译时,你可以做到
int havingSameSize[sizeof(array_size(a))];
因为函数永远不会被实际调用,所以不需要定义它,因此它没有实体.希望我能稍微澄清一下这个问题.
可以这样想,假设你有一堆功能:
// 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...
现在当你调用它时,会调用哪个函数?
int a[2]; array_size(a);
现在,如果你对数组化进行模板化,你会得到:
templatesize_t array_size(const int (&)[n]) { return n; }
编译器将尝试实例化array_size的一个版本,该版本匹配您调用它的任何参数.因此,如果使用10个int的数组调用它,它将实例化array_size,其中n = 10.
接下来,只是模板化类型,因此您可以使用不仅仅是int数组来调用它:
templatesize_t array_size(const T (&)[n]) { return n; }
而且你已经完成了.
编辑:有关的说明(&)
需要括号&
来区分int引用数组(非法)和引用int数组(你想要的).由于优先级[]
高于&
,如果你有声明:
const int &a[1];
由于运算符优先级,最终会得到一个对int引用的单元素数组.如果你想&
先应用,你需要用括号强制它:
const int (&a)[1];
现在你有了一个int元素数组的const引用.在函数参数列表中,如果不使用参数名称,则无需指定参数名称,因此可以删除名称,但保留括号:
size_t array_size(const int (&)[1])