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 ...
随机推荐
- UVA 11136 Hoax or what (multiset)
题目大意: 超时进行促销.把账单放入一个箱子里 每次拿取数额最大的和最小的,给出 最大-最小 的钱. 问n天总共要给出多少钱. 思路分析: multiset 上直接进行模拟 注意要使用long lo ...
- android ImageView加圆角
1.attrs添加 <declare-styleable name="RoundImageView"> <attr name="circle" ...
- host文件常用地址
#+UPDATE_TIME 2016-02-16 19:52:05 UTC+8#+MESSAGE#################################################### ...
- PHPExcel使用-使用PHPExcel导入文件
导入步骤: 1. 实例化excel读取对象 2. 加载excel文件 ----------------> ( 1>. 全部加载. 2>. 选择加载. ) 3. 读取excel文件 - ...
- 既生list何生tuple
python中list是可以修改的;若要创建一系列不可修改的元素时,就需要tuple. 用 tuple 的好处: 1.tuple 比 list 操作速度快.如果您定义了一个值的常量集,并且唯一要用它做 ...
- 多线程下载文件,ftp文件服务器
1: 多线程下载文件 package com.li.multiplyThread; import org.apache.commons.lang3.exception.ExceptionUtils; ...
- PAT 1019 General Palindromic Number[简单]
1019 General Palindromic Number (20)(20 分) A number that will be the same when it is written forward ...
- [Leetcode] 49. Group Anagrams_Medium
Given an array of strings, group anagrams together. Example: Input: ["eat", "tea" ...
- JAVA如何调用mysql写的存储过程
存储过程是干什么的,自己百度,百度上讲的比我讲的好.为什么要用存储过程,这样可以提高效率.废话少说,直接上代码: 首先说一下语法:在mysql中写存储过程 DELIMITER $$ CREATE /* ...
- GIC400简介
GIC400是arm公司的中断控制IP,提供axi4接口,主要功能: 1)中断的使能(enable,mask); 中断的优先级(poriority); 中断的触发条件(level-sensitive ...