在刚开始学习《C++ Primer》的时候遇到了 end 函数, 感觉很神奇, 但又很迷惑: 为什么能获得数组的尾后指针呢? 编译器也不会在内存中申请一块空间放数组元素的个数啊! 最近再一次遇到了 end 就看了一下它的实现终于明白了.
先说以下 C 语言中获得数组元素个数的方法.
- int arr[] = {
- 1, 2, 3
- };
- size_t n = sizeof(arr) / sizeof(int); //n 为元素个数
sizeof 返回一个常量表达式, 是在编译时期确定返回值的. 也就是说在编译时期是可以知道数组的长度的.
再看看 C++ 标准库中 end 的实现(关键部分: 非类型模板参数 N 及函数形参):
- // 编译器再编译时期会根据数组的元素个数来代替 N, 从而实例化模板
- template<typename T, size_t N>
- inline constexpr T* end(T (&arr)[N]) { // 由于不能拷贝一个数组, 所以将参数定义为了数组的引用
- return arr + N; // 指针和一个整数 N(数组元素个数)相加, 从而返回数组 arr 的尾后指针
- }
模板参数列表中的 N 是一个非类型模板参数, 而非类型模板参数是在编译时期被确定的常量表达式. end 函数的形参是一个 (长度为 N) 数组的引用, 因为 N 是一个非类型模板参数, 所以编译器会在编译时期 (前面说过, 在编译时期是可以确定数组长度的) 用数组的长度来初始化 N. 最后将 arr 和 N 相加即获得了数组的尾后指针.
来源: https://www.cnblogs.com/yuanyb/p/11402831.html