C/C++中如果一个函数接受一个数组作为参数,那么数组将会被退化为指针,如果定义如下代码:

//数组arr的大小未知。
int arrsize(int arr*) {
cout << "element num : " << sizeof(arr) / sizeof(arr[0]) << endl; //1
}
  • 1
  • 2
  • 3
  • 4

在上面那段代码中不仅得到的数组大小是不正确的,还会出现让调用则不明白是传递int变量的地址,还是传递一个指针(数组),为了解决第二个歧义现象,我们可以定义如下:

//数组arr的大小依旧未知。
int arrsize(int arr[]) {
cout << "element num : " << sizeof(arr) / sizeof(arr[0]) << endl; //1
}
  • 1
  • 2
  • 3
  • 4

即使我们按上面那种定义,但数组的的大小我们依旧不知道,但现在编译器还会提示类似如下警告:

 warning: ‘sizeof’ on array function parameter ‘arr’ will return size of ‘int*’ [-Wsizeof-array-argument]
  • 1

为了更好的解决上面的问题我们可以考虑使用一个引用形参,可以有如下代码:

//数组arr的大小必须是12,否则会报错。
int arrsize_const_size(int (&arr)[12]) {
cout << "element num : " << sizeof(arr) / sizeof(arr[0]) << endl;//12
}
  • 1
  • 2
  • 3
  • 4
  • 5

即使我们使用引用形参解决了,在函数内部我们无法正确获取数组大小的问题,但更复杂的问题出现了,我们只能接受固定数量的大小的数组,解决这个问题,我们可以通过一种很常规的手法定义函数如下:

 //指定一个数组大小n
int arrsize_n(int arr[], int n) { }
  • 1
  • 2
  • 3
  • 4
  • 5

上面虽然解决了,但我们多传递了一个参数,调用代码看起来没有前两个更加简洁了,虽然问题被很好的解决了,为了更好的解决这个问题我们可以把推断数组大小的事交个编译器,使用非类型模板参数。

template<int n>
int arrsize_template_size(int (&arr)[n]) {
cout << "element num : " << sizeof(arr) / sizeof(arr[0]) << endl;//12
cout << "n : " << n << endl;//12
for (int i = 0; i < n; i++) {
cout << "arr[" << i << "] = " << arr[i] << endl;
}
return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

下面给出完整的测试代码:

#include <iostream>

using namespace std;

//数组arr的大小未知。
int arrsize(int arr[]) {
cout << "element num : " << sizeof(arr) / sizeof(arr[0]) << endl;//1
return 0;
}
//数组arr的大小必须是12,否则会报错。
int arrsize_const_size(int (&arr)[12]) {
cout << "element num : " << sizeof(arr) / sizeof(arr[0]) << endl;//12
return 0;
} //指定一个数组大小n
int arrsize_n(int arr[], int n) {
return 0;
} template<int n>
int arrsize_template_size(int (&arr)[n]) {
cout << "element num : " << sizeof(arr) / sizeof(arr[0]) << endl;//12
cout << "n : " << n << endl;//12
for (int i = 0; i < n; i++) {
cout << "arr[" << i << "] = " << arr[i] << endl;
}
return 0;
} int main() { int arr[12] = {
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
};
int arr1[16] = {
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16,
}; arrsize(arr);
arrsize_const_size(arr);
cout << "-------------------------------------" << endl;
arrsize_template_size(arr);
cout << "-------------------------------------" << endl;
arrsize_template_size(arr1);
cout << "-------------------------------------" << endl;
return 0;
} 如果array类型也是复用的话,那么就有最终版本:
template<typename T,int n>
void print_arr_in_tpl(T (&arr)[n]){
std::cout << "element num : " << sizeof(arr) / sizeof(arr[]) << std::endl;//
for(int i=;i<n;++i){
std::cout<<arr[i]<<std::endl;
}
}

哈哈, 大家拿去用吧



论C++如何优雅的使用数组的更多相关文章

  1. php如何优雅地把数组传递给前端js脚本?

    比如说http://echarts.baidu.com/demo...这个例子中,一般里面的timeData数组都是数据库的所有记录的单独某一个列的集合,而例子中第149行的 data:[ 1,2,3 ...

  2. flexible array柔性数组、不定长的数据结构Struct详解

    柔性数组,这个名词对我来说算是比较新颖的,在学习跳跃表的实现时看到的.这么好听的名字,的背后到底是如何的优雅. 柔性数组,其名称的独特和迷惑之处在于“柔性”这个词.在C/C++中定义数组,是一个定长的 ...

  3. 深入浅出ES6(十七):展望未来

    作者 Jason Orendorff  github主页  https://github.com/jorendorff 出于对文章长度的考虑,我们还保留了一些尚未提及的新特性,在最后的这篇文章中我会集 ...

  4. python 随笔

    python 学习笔记 运算符重载 PYTHON-进阶-魔术方法小结(方法运算符重载) python有着像C++相似的运算符重载,只需要在类中重写__add__.sub 等方法,就可以直接对对象进行 ...

  5. JavaScript的动态特性(通过eval,call,apply和bind来体现)

    JavaScript的动态特性(通过eval,call,apply和bind来体现) JavaScript是一种基于面向对象的.函数式的.动态的编程语言.现在发展到已经可以用在浏览器和服务器端了. 这 ...

  6. Java:不得不知的Object类

    目录 一.equals 1.equals与==有啥区别? 2.equals方法的规范 3.instanceof 和getClass() 4.其他总结 二.hashCode 1.hashCode的规范 ...

  7. 优雅的数组降维——Javascript中apply方法的妙用

    将多维数组(尤其是二维数组)转化为一维数组是业务开发中的常用逻辑,除了使用朴素的循环转换以外,我们还可以利用Javascript的语言特性实现更为简洁优雅的转换.本文将从朴素的循环转换开始,逐一介绍三 ...

  8. php在没用xdebug等调试工具的情况下如何让调试内容优雅地展现出来?--php数组格式化

    不知道各位猿猿们有没有碰到过类似的情况.装的PHP环境没有xdebug,而又经常用到数组.调试的时候也需要经常查看数组的结构和字段内容,用var_dump打印出来的数组内容总是杂乱无章.实在无法忍受, ...

  9. [转] 怎样快速而优雅地遍历 JavaScript 数组

    我们一般用循环来遍历数组,而循环一直是 JavaScript 性能问题的常见来源,有时循环用得不好会严重降低代码的运行速度.例如,遍历数组时,我们会很自然地写出下面这种代码: // 未优化的代码1 v ...

随机推荐

  1. Android系统之Broadcom GPS 移植

    1.      内核部分的移植: 内核部分的移植基本上就是对芯片上下电,建立数据结构体,打通GPS通信的串口通道,以及建立文件设备结点供上层调用.所建立的文件结点是针对Power_enable和Res ...

  2. Android 4.1.2系统添加重启功能

    对于Android的的手机或者平板长期使用,感觉会出现慢的情况,所以偶尔还是需要重启一下,而长按电源键弹出的菜单又没有重启选项,所以特在此记录自己添加这个功能的过程. 首先关机的那个弹出菜单是在fra ...

  3. linux下32位汇编调用规则

    传递给系统调用的参数必须安装参数顺序一次放到寄存器中,当系统调用完成后,返回值放在eax中: 当系统调用参数<=5个时: eax中存放系统调用的功能号,传递给系统调用的参数顺序依次放到寄存器:e ...

  4. C语言中如何写一个简单可移植而又足够随机的随机数生成器

    在C语言中标准库中的随机数产生函数的返回可能不是最优的,因为有些随机数生成器的低位并不随机,而另一些返回随机数的函数实现上又太复杂鸟.所以rand()%N并不是一个好方法,牛人给出的建议是使用: ra ...

  5. Java核心技术第四章——2.final 和 static

    final实例域 实例域(对象的属性)可修饰为final.修饰为final后,在构建对象时必须初始化这个实例域.若没有在实例域进行初始化,那么必须在每个构造器内初始化这个实例域(否则会编译错误). 表 ...

  6. 高并发教程-基础篇-之nginx负载均衡的搭建

    温馨提示:请不要盲目的进行横向扩展,优先考虑对单台服务器的性能优化,只有单台服务器的性能达到最优化之后,集群才会被最大的发挥作用. 一.架构图: 服务器准备:3台,ubuntu16.04系统maste ...

  7. PLSQL学习教程(全)

    基于ORACLE9i+PL/SQLDeveloper7.1.4) 课程 一 PL/SQL 基本查询与排序 本课重点: 1.写SELECT语句进行数据库查询 2.进行数学运算 3.处理空值 4.使用别名 ...

  8. oracle面试题目总结

    阿里巴巴公司DBA笔试题  http://searchdatabase.techtarget.com.cn/tips/2/2535002.shtml   注:以下题目,可根据自己情况挑选题目作答,不必 ...

  9. iframe之局部刷新

      例如: <iframe src="1.htm" name="ifrmname" id="ifrmid"></ifram ...

  10. datetime的精度

    最近有需要将分钟线的数据进行内联拼接,但时间没有必要精确到秒,微秒. df['datetime'] = pd.to_datetime(df['datetime']) df = df.set_index ...