今天看 STL 源码的时候注意到一个有意思的地方,获取定长数组的长度 std::size
函数的简单实现如下:
如果阅读这个代码有些困难,它的一个特化实现可以简单写成下面这样:
看到这个函数我愣了几秒钟,这个函数的参数 const int (&)[_Size]
里的 (&)
是什么鬼?
根据 & 符号出现的位置判断,它应该是表示数组引用,因为平时从来没用过数组的引用这种写法,赶紧敲一行代码试试
确认了自己的判断,也就不难理解 std::size
的原理了。但是突然感觉自己的记忆出现了偏差,几年前课本上教的传递数组的方式应该是下面这样啊:
心里有了一些疑问,用传值的方式传递的数组,和传递引用的方式有什么区别吗?重新实现一个传值方式的 size 函数测试一下
发现编译直接报错了,报错信息是参数列表不匹配,不能从 int[10]
为 const int [_Size]
推导模板参数。更有意思的是,宇宙第一编译器提示我 size 函数的签名是这样的
原来模板实例化以后产生的函数所需参数是 const int *
类型的,所以 _Size 模板参数是无法推导的,所以如果我直接传递一个 _Size 进去
编译器会好心的告诉我,len 的结果是 9,和 arr 的长度无关。
难道之前课本上看到的方法是错误的吗?再写个函数测试一下
编译器又开心的提示我,len 的值是 4,验证了 int arr[10]
在参数中会退化成 int*
。为了进一步验证这一点,再写一个函数测试一下:
也就是说,所谓的传递定长数组其实编译器并不会进行检查,而且长度不一样也是不会报错的。
如果你在网站上直接搜索 C++传递数组
,大部分资料告诉你的仍然是错误的
看起来,想要学好 C++还需要一些侦探思维,什么东西都要怀疑一下呢。