论C++如何优雅的使用数组
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++如何优雅的使用数组的更多相关文章
- php如何优雅地把数组传递给前端js脚本?
比如说http://echarts.baidu.com/demo...这个例子中,一般里面的timeData数组都是数据库的所有记录的单独某一个列的集合,而例子中第149行的 data:[ 1,2,3 ...
- flexible array柔性数组、不定长的数据结构Struct详解
柔性数组,这个名词对我来说算是比较新颖的,在学习跳跃表的实现时看到的.这么好听的名字,的背后到底是如何的优雅. 柔性数组,其名称的独特和迷惑之处在于“柔性”这个词.在C/C++中定义数组,是一个定长的 ...
- 深入浅出ES6(十七):展望未来
作者 Jason Orendorff github主页 https://github.com/jorendorff 出于对文章长度的考虑,我们还保留了一些尚未提及的新特性,在最后的这篇文章中我会集 ...
- python 随笔
python 学习笔记 运算符重载 PYTHON-进阶-魔术方法小结(方法运算符重载) python有着像C++相似的运算符重载,只需要在类中重写__add__.sub 等方法,就可以直接对对象进行 ...
- JavaScript的动态特性(通过eval,call,apply和bind来体现)
JavaScript的动态特性(通过eval,call,apply和bind来体现) JavaScript是一种基于面向对象的.函数式的.动态的编程语言.现在发展到已经可以用在浏览器和服务器端了. 这 ...
- Java:不得不知的Object类
目录 一.equals 1.equals与==有啥区别? 2.equals方法的规范 3.instanceof 和getClass() 4.其他总结 二.hashCode 1.hashCode的规范 ...
- 优雅的数组降维——Javascript中apply方法的妙用
将多维数组(尤其是二维数组)转化为一维数组是业务开发中的常用逻辑,除了使用朴素的循环转换以外,我们还可以利用Javascript的语言特性实现更为简洁优雅的转换.本文将从朴素的循环转换开始,逐一介绍三 ...
- php在没用xdebug等调试工具的情况下如何让调试内容优雅地展现出来?--php数组格式化
不知道各位猿猿们有没有碰到过类似的情况.装的PHP环境没有xdebug,而又经常用到数组.调试的时候也需要经常查看数组的结构和字段内容,用var_dump打印出来的数组内容总是杂乱无章.实在无法忍受, ...
- [转] 怎样快速而优雅地遍历 JavaScript 数组
我们一般用循环来遍历数组,而循环一直是 JavaScript 性能问题的常见来源,有时循环用得不好会严重降低代码的运行速度.例如,遍历数组时,我们会很自然地写出下面这种代码: // 未优化的代码1 v ...
随机推荐
- Android系统之Broadcom GPS 移植
1. 内核部分的移植: 内核部分的移植基本上就是对芯片上下电,建立数据结构体,打通GPS通信的串口通道,以及建立文件设备结点供上层调用.所建立的文件结点是针对Power_enable和Res ...
- Android 4.1.2系统添加重启功能
对于Android的的手机或者平板长期使用,感觉会出现慢的情况,所以偶尔还是需要重启一下,而长按电源键弹出的菜单又没有重启选项,所以特在此记录自己添加这个功能的过程. 首先关机的那个弹出菜单是在fra ...
- linux下32位汇编调用规则
传递给系统调用的参数必须安装参数顺序一次放到寄存器中,当系统调用完成后,返回值放在eax中: 当系统调用参数<=5个时: eax中存放系统调用的功能号,传递给系统调用的参数顺序依次放到寄存器:e ...
- C语言中如何写一个简单可移植而又足够随机的随机数生成器
在C语言中标准库中的随机数产生函数的返回可能不是最优的,因为有些随机数生成器的低位并不随机,而另一些返回随机数的函数实现上又太复杂鸟.所以rand()%N并不是一个好方法,牛人给出的建议是使用: ra ...
- Java核心技术第四章——2.final 和 static
final实例域 实例域(对象的属性)可修饰为final.修饰为final后,在构建对象时必须初始化这个实例域.若没有在实例域进行初始化,那么必须在每个构造器内初始化这个实例域(否则会编译错误). 表 ...
- 高并发教程-基础篇-之nginx负载均衡的搭建
温馨提示:请不要盲目的进行横向扩展,优先考虑对单台服务器的性能优化,只有单台服务器的性能达到最优化之后,集群才会被最大的发挥作用. 一.架构图: 服务器准备:3台,ubuntu16.04系统maste ...
- PLSQL学习教程(全)
基于ORACLE9i+PL/SQLDeveloper7.1.4) 课程 一 PL/SQL 基本查询与排序 本课重点: 1.写SELECT语句进行数据库查询 2.进行数学运算 3.处理空值 4.使用别名 ...
- oracle面试题目总结
阿里巴巴公司DBA笔试题 http://searchdatabase.techtarget.com.cn/tips/2/2535002.shtml 注:以下题目,可根据自己情况挑选题目作答,不必 ...
- iframe之局部刷新
例如: <iframe src="1.htm" name="ifrmname" id="ifrmid"></ifram ...
- datetime的精度
最近有需要将分钟线的数据进行内联拼接,但时间没有必要精确到秒,微秒. df['datetime'] = pd.to_datetime(df['datetime']) df = df.set_index ...