c++之数组形参
1.问题,最近看项目log模块,_log模板函数中的一个参数竟然看蒙x了。函数原形是这样:
template<size_t size>
void _Log(char (&strDest)[size], const char *scetion, const char *key, const char *msg, va_list &parm);
对!就是 char (&strDest)[size]没有看懂。这个传进来的是个字符串数组。
2.翻开c++圣经<c++primer>,找到答案。设计模板类型形参中的 非类型形参和数组引用类型形参。
首先,数组作为形参,有引用和非引用两种形式。一般我们使用非引用形式,也就是将形参定义为数组元素类型的指针,一共有三个等价形式:
1.void func(int *p);
2.void func(int p[]);
3.void func(int p[10]);
其中第三个显示的表明 调用该函数时,所传递的数组最多有10个元素。但是实际上编译器会忽略为任何数组指定的形参长度,换句话说,第三个函数声明中的10,其实是被编译器忽略的。
当我们调用上边的函数时,传递数组名时,数组名会自动转化为指向数组第一个元素的指针。也就是该指针所存放的是数组第一个元素的地址。 然后形参复制的是这个指针指向的地址。
然后,当数组作为形参,采用引用的方式时,形式是这样:
1.void func(int (&p)[10]);
当调用此函数时,必须传递的是 具有10个int型元素的数组。类似这样
int a[10] = {};
func(a);
如果这样 int b[2] = {}; func(b); 是不正确的,因为b不是10个元素。当形参是引用类型时,理解引用的含义很重要。引用就是一个变量的别名,但是终究是该变量自己。
同时,使用引用时,没有复制的环节,大多时候会节省空间,提升效率。
3.但是,我们可以看出,以上形式的数组的引用型形参,是很不方便的。因为传递数组时,存在类型和长度的双重限制。
那么有没有一种方法,能够解决上述问题呢? 既能用到引用的有点,同时又能避免长度带来的限制?
答案就是采用 1. 中的模板函数以及使用非类型模板形参。
template<size_t size>
void func(int (&p)[size]){ ... }
圣经中讲到:模板非类型形参是模板定义内部的常量值,在需要常量表达式的时候,可使用非类型形参指定数组的长度, 当调用 func是,编译器会从数组的实参计算非类型形参的值,也就是编译器替我们
计算好了size的值,从而省去我们自己传递长度。这样一来,就可以传递数组元素相同的数组了,不必担心长度。从而避免了2中的缺点
这样一来:
int a[10], b[2];
func(a);func(b)都可以正确调用,同时size的值为a和b的数组长度。
另外一点需要说明,尽管用了模板的非类型形参,让我们可以省去数组长度的限制,但是实际上,编译器会产生两个func的实例 func<10>, func<2>.
如果此时声明 int c[10]; func(c); 此时a和c将使用相同的实例。
这基于: 对于模板的非类型形参而言,求值结果形同的表达式将认为是等价的。
因此 a和c调用 func(int (&p)[10]), b调用 func(int (&p)[2]).
4.至此,_log函数中的第一个形参已经弄清--数组的应用型形参。同时利用模板的非类型形参,除去了数组长度的限制。
水平有限,欢迎指正错误。
c++之数组形参的更多相关文章
- C++——数组形参退化为指针
数组做形参退化为指针 如果数组作为函数参数,则数组形参会退化为指针,以下代码在编译器看来是等价的 ]); ]); void fun3(int a[]); void fun4(int *a); #inc ...
- Linux C\C++基础——数组形参的使用
1.数组形参 ]) void fun(int a[]) void fun(int *a) ],int n) void fun(char*p[],int n) void fun(char**p,int ...
- C: 数组形参
知识这个东西,真是知道的越多就不知道的越多,C/C++这塘水得多深啊,哈哈.看下面3个片段:<一> 1 void fun(char a[100]) { 2 fprintf( ...
- 怎样只接受固定长度数组为参数 & 数组形参
注意,对于多维数组的情况.
- 【C语言学习】《C Primer Plus》第10章 数组和指针
学习总结 1.数组初始化方式: int a[]={1,2,3} int a[SIZE]={1,2,3} //SIZE是宏定义,数组初始化个数不能大于SIZE,否则报错:当个数小 //SIZE,自动补0 ...
- C语言基础--数组及相关
概念: 一堆相同类型的数据的有序集合 格式: 元素类型 数组名称[ 元素个数 ] 定义数组: // 定义了一个名称叫做scores的数组, 数组中可以存放3个int类型的数据 ]; // 只要定义一 ...
- 用C#中的params关键字实现方法形参个数可变
个人认为,提供params关键字以实现方法形参个数可变是C#语法的一大优点.在方法形参列表中,数组类型的参数前加params关键字,通常可以在调用方法时代码更加精练. 例如,下面代码: class P ...
- c语言学习之基础知识点介绍(十):数组
本节主要介绍数组. 一.数组 /* 数组:一个变量可以存n个变量. 语法:类型 数组名[长度(正整数)]; 例如:int score[5];//定义了一个int类型的数组,长度为5,可以保存5个数据. ...
- C语言数组
在C语言中,对于三维或三维以上数组的使用并没有很好的支持,而且使用率也非常的低,后面会对三维数组做一些简单的分析,这篇文章主要以二维数组来探讨一些C语言中数组使用的相关概念和技巧. 1 一个var[i ...
随机推荐
- [运维-安全]CentOS7.0环境下安装kangle和easypanel
一.康乐简介 主要特点1.免费开源kangle技术团队希望国人拥有一款真正好用.易用.实用的国产web服务器.2.跨平台可在linux.windows.freebsd.openbsd.netbsd.s ...
- vue学习之webpack
本质上,Webpack是一个现代 JavaScript应用程序的静态模块打包器(module bundler).当 Webpack处理应用程序时,它会递归地构建一个依赖关系图(dependency g ...
- 完成向后台添加用户的ssm项目,完整版
1:ssm框架整合 1.1添加maven依赖pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns: ...
- [LeetCode] 529. Minesweeper_ Medium_ tag: BFS
Let's play the minesweeper game (Wikipedia, online game)! You are given a 2D char matrix representin ...
- iOS UI基础-1.0加法计算器
1.打开Xcode,新建一个项目 2.Single View Application是最适合初学者的模板 3.填写该应用相关信息 4.搭建UI界面 项目创建完毕后,自动帮我们做了很多配置,也自动生成了 ...
- Qt计时器
在Qt中使用定时器有两种方法,一种是使用QObiect类的定时器:一种是使用QTimer类.定时器的精确性依赖于操作系统和硬件,大多数平台支持20ms的精确度. ■.QObject类的定时器QObje ...
- DIV CSS 绘制风车
我得说,CSS和DIV是个有趣的东西. 由于脑袋一无聊,突然想,画个DIV风车怎么样,于是就画了一个. border的风格可以自主选择. 上代码: <style> *{ margin:0p ...
- Unirest-拼装http请求发送rest接口
public static Integer getInfo(String name) { HttpResponse<Integer> httpResponse = null; try { ...
- Codeforces Round #440 (Div. 2, based on Technocup 2018 Elimination Round 2) C. Maximum splitting
地址: 题目: C. Maximum splitting time limit per test 2 seconds memory limit per test 256 megabytes input ...
- hdu3511 Prison Break 圆的扫描线
地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=3511 题目: Prison Break Time Limit: 10000/5000 MS ( ...