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. 总结C语言在嵌入式开发中应用的知识点(文件数据的加密与解密)

    <span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255) ...

  2. LeetCode之“链表”:Remove Duplicates from Sorted List && Remove Duplicates from Sorted List II

    1. Remove Duplicates from Sorted List 题目链接 题目要求: Given a sorted linked list, delete all duplicates s ...

  3. Hadoop 的 TotalOrderPartitioner

    Partition所处的位置 Partition位置 Partition主要作用就是将map的结果发送到相应的reduce.这就对partition有两个要求: 1)均衡负载,尽量的将工作均匀的分配给 ...

  4. mysql清空表

    清空某个mysql表中所有内容 delete from 表名; truncate table 表名; 不带where参数的delete语句可以删除mysql表中所有内容,使用truncate tabl ...

  5. 内核调试神器SystemTap — 简介与使用(一)

    a linux trace/probe tool. 官网:https://sourceware.org/systemtap/ 简介 SystemTap是我目前所知的最强大的内核调试工具,有些家伙甚至说 ...

  6. obj-c编程10:Foundation库中类的使用(3)[文件管理]

    好吧,不管神马系统都无可避免的要说到文件,目录,路径(PATH)管理的内容,下面我们来看看在F库中对他们的支持.我简单看了下,不谈其他光从方法命名来说就多少显得有点复杂,如果和ruby相比就呵呵了. ...

  7. C# PDF Page操作——设置页面切换按钮

    概述 在以下示例中,将介绍在PDF文档页面设置页面切换按钮的方法.示例中将页面切换按钮的添加分为了两种情况,一种是设置按钮跳转到首页.下页.上页或者最后一页,另一种是设置按钮跳转到指定页面.两种方法适 ...

  8. 访问PHP文件时出现An error occurred.

    服务器配置ubuntu16,nginx,php5.6-fpm 我的问题是用户组没有权限导致出现访问PHP文件时An error occurred.,访问Html页面正常. 查看Nginx日志报错(路径 ...

  9. Linux下转换文件从GBK到UTF-8

    iconv -f gbk -t utf- source-file -o target-file

  10. 智能合约最佳实践 之 Solidity 编码规范

    每一门语言都有其相应的编码规范, Solidity 也一样, 下面官方推荐的规范及我的总结,供大家参考,希望可以帮助大家写出更好规范的智能合约. 命名规范 避免使用 小写的l,大写的I,大写的O 应该 ...