C++标准库函数 end 的实现原理(非类型模板参数)

在刚开始学习《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

时间: 2024-10-11 23:16:49

C++标准库函数 end 的实现原理(非类型模板参数)的相关文章

C++非类型模板参数

对于函数模板与类模板,模板参数并不局限于类型,普通值也可以作为模板参数.在基于类型参数的模板中,你定义了一些具体的细节来加以确定代码,直到代码被调用时这些细节才被真正的确定.但是在这里,我们面对的是这些细节是值,而不是类型,当要使用基于值的模板时,必须显式地指定这些值,才能够对模板进行实例化. 本文地址:http://www.cnblogs.com/archimedes/p/cpp-template-type.html,转载请注明源地址. 在上篇文章(C++类模板)中我们介绍了一个stack类模

非类型模板参数

对于函数模板与类模板,模板参数并不局限于类型,普通值也可以作为模板参数.在基于类型参数的模板中,你定义了一些具体的细节来加以确定代码,直到代码被调用时这些细节才被真正的确定.但是在这里,我们面对的是这些细节是值,而不是类型,当要使用基于值的模板时,必须显式地指定这些值,才能够对模板进行实例化. 非类型的类模板参数 创建类的头文件 #include<stdexcept> #include<iostream> using namespace std; template<typen

C++模板编程 - 第四章 非类型模板参数

一个例子是 1 template<typename T, int MAXSIZE> 2 class Stack {}; 在这里我就想起了C语言是怎么弄数据结构的,不得不说模板是很方便的东西.上面的例子是一个类模板,函数模板其实也是类似的. 浮点数和类对象是不允许作为非类型模板参数的. 对上面这句话的补充:这是历史原因,C++ Templates的作者认为C++在未来可能会允许使用浮点数和类对象作为非类型模板参数. 不太好理解的是这个例子 1 template<char const * n

[013]模板-非类型模板参数

在模板中,除了定义类型参数,我们还可以定义非类型参数.例如: temlate<unsigned N, unsigned M> int foo(const char (&p1)[N], const char (&p2)[M]) { return strcmp(p1,p2); } 但是需要注意的是:编译器会在一个字符串字面常量的末尾插入一个空字符作为终结符. 例如我们调用 foo("hi", "mom"); 实际上编译器会实例化如下版本 in

读boost::multi_array有感,多维数组实现(非类型模板,偏特化)

开发环境: VS2002(VC7) 本文做如下简化: 1,假定所有维元素都是5. 2,不考虑const的[]. 3,由于只是熟悉原理,不考虑各种异常情况. 问题一,请实现一个一维整形数组,只需重载[]. 问题二,请实现一个二维整形数组,只需重载[]. 源码如下: class CIntArray1 { public: int& operator[](int index) { return m_pData[index]; } protected: int m_pData[5]; }; class C

C语言中最常用标准库函数

标准头文件包括: <asset.h>      <ctype.h>       <errno.h>       <float.h> <limits.h>      <locale.h>       <math.h>        <setjmp.h> <signal.h>     <stdarg.h>      <stddef.h>      <stdlib.h>

C/C++语言的标准库函数malloc/free与运算符new/delete的区别

概括地说 1.malloc与free是C++/C的标准库函数,new/delete是C++的运算符,它们都可用于申请动态内存和释放内存. 2.对于非内部数据类型的对象而言,只用malloc/free无法满足动态对象的要求.对象在创建的同时,要自动执行构造函数,对象在消亡之前要自动执行析构函数.而由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free. 3.因此C++语言需要一个能完成动态内存分配和初始化工作的运算符

C++/C语言的标准库函数与运算符的区别new/delete malloc/free

malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符.它们都可用于申请动态内存和释放内存.下面来看他们的区别. 一.操作对象有所不同 malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符.对于非内部数据类型的对象而言,光用malloc/free无法满足动态对象的要求. 对象在创建的同时要自动执行构造函数,对象消亡之前要自动执行析构函数.由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能把执行构造函数

c++11 标准库函数 std::move 和 完美转发 std::forward

c++11 标准库函数 std::move 和 完美转发 std::forward #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #include <vector> #include <map> // C++中还有一个被广泛认同的说法,那就是可以取地址的.有名字的就是左值,反之,不能取地址的.没有名字的就是右值. // 相对于左值,右值表示字面常量.表达式.函数的非