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 ...
随机推荐
- 1分钟了解协同过滤,pm都懂了
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/z50L2O08e2u4afToR9A/article/details/79565720 projec ...
- 15 jmeter分布式性能测试
背景由于jmeter本身的瓶颈,当需要模拟数以千计的并发用户时,使用单台机器模拟所有的并发用户就有些力不从心,甚至还会引起Java内存溢出的错误.要解决这个问题,可以使用分布式测试,运行多台机器运用所 ...
- [py]列表生成式-支持条件,多值的拼接
列表生成式 代码简洁一些 支持多条件, 过滤,或拼接某些值 支持返回多值 是一种生成式 # 生成一个列表 print(list(range(1, 11))) # 生成一个列表x^2 ## 方法1: 返 ...
- nodejs加WebSocket,聊天工具
1.WebSocket必须要与服务器连接,所以这里采用node起服务,这里用到了ws,,也有人用nodejs-websocket 2.首先 npm install ws 3.新建一个server.js ...
- python 皮尔森相关系数
皮尔森理解 皮尔森相关系数(Pearson correlation coefficient)也称皮尔森积矩相关系数(Pearson product-moment correlation coeffic ...
- SQL Expression Language Tutorial 学习笔记二
11. Using Textual SQL 直接使用 SQL 如果实在玩不转, 还是可以通过 test() 直接写 SQL. In [51]: s = text( ...: "SELECT ...
- 如何在SQL Server查询语句(Select)中检索存储过程(Store Procedure)的结果集?
如何在SQL Server查询语句(Select)中检索存储过程(Store Procedure)的结果集?(2006-12-14 09:25:36) 与这个问题具有相同性质的其他描述还包括:如何 ...
- Android开发中,系统是如何区分不同的App的(转自csdn)
转自:http://bbs.csdn.net/topics/391868975?page=1 1判断是否为同一个app,仅仅是包名,签名是保证你的app不被第三方恶意替换.当包名相同,但签名不同时,系 ...
- JS多重判断 / ES6 includes
Array.includes () 判断数组是否包含某个元素 直接返回true或者false表示是否包含元素,对NaN一样能有有效 const arr = ['1', '2', 'a', 'b' , ...
- Python: 序列list:保持元素顺序同时消除重复值
问题:怎样在Python的一个序列上面保持元素顺序的同时消除重复的值?answer:如果序列上的值都是hashable 类型,那么可以很简单的利用集合或者生成器来解决这个问题. eg1: def de ...