[转]数组引用:C++ 数组做参数 深入分析
"数组引用"以避免"数组降阶"(本文曾贴于VCKBASE\C++论坛)
受[hpho]的一段模板函数的启发,特写此文,如有雷同,实在遗憾。
数组降阶是个讨厌的事,这在C语言中是个无法解决的问题,先看一段代码,了解什么是"数组降阶"
#include <IOSTREAM>
using namespace std;
void Test( char array[20] )
{
cout << sizeof(array) << endl; // 输出 4
}
int main( void )
{
char array[20] = { 0 };
cout << sizeof(array) << endl; // 输出 20
Test( array );
}
为什么同样申明的array一个输出20一个输出4?这是因为void Test( char array[20] )中的array被降阶处理了,void Test( char array[20] )等同于void Test( char array[] ),也等同于void Test( char* const array ),如果你BT(开玩笑),它也等同于void Test( char array[999] )。
就是说
void Test( char array[20] )
{
cout << sizeof(array) << endl;
}
被降成
void Test( char* const array )
{
cout << sizeof(array) << endl; // 既然是char*,当然输出4
}
这样一来问题大了,你完全可以定义一个不足20个元素的数组,然后传给Test,坐等程序崩溃。在一些要求较高的场合就不能使用数组做参数,真TMD心有不甘。
那么在C语言中怎样解决这个问题?
没办法,应该说没有好办法。a:做个结构,其中仅一个char array[20],然后用这个结构指针代替char array[20]。可见这是个很繁琐的办法,且不直观;b:在Test内部使用_msize来计算array长度。这更不行,首先它使得错误的发现被推迟到运行期,而不是编译期,其次_msize长度/元素大小>=array长度,也就是说就是new char[19]和new array[20]分配的大小是一样的,这样一来,虽不至于导致程序崩溃,但运算结果却不正确。
感谢[hpho],受其启发,C++中有C所没有的"引用",但数组引用是怎样申明的呢?经过几番试验,Look
#include <IOSTREAM>
using namespace std;
void Test( char (&array)[20] ) // 是不是很像 char *p[20] 和 char (*p)[20] 的区别?
{
cout << sizeof(array) << endl;
}
int main( void )
{
char array[20] = { 0 };
cout << sizeof(array) << endl;
Test( array );
}
在 C++中,数组永远不会按值传递,它是传递第一个元素,准确地说是第 0个 的指针。
例如,如下声明 :
void putValues( int[ 10 ] );
被编译器视为
void putValues( int* );
数组的长度与参数声明无关,因此,下列三个声明是等价的:
// 三个等价的 putValues()声明
void putValues( int* );
void putValues( int[] );
void putValues( int[ 10 ] );
因为数组被传递为指针 所以这对程序员有两个含义:
1. 在被调函数内对参数数组的改变将被应用到数组实参上而不是本地拷贝上,当用作实参的数组必须保持不变时,程序员需要保留原始数组的拷贝函数可以通过把参数类型声明为 const 来表明不希望改变数组元素。
void putValues( const int[ 10 ] );
2. 数组长度不是参数类型的一部分,函数不知道传递给它的数组的实际长度,编泽器也不知道,当编译器对实参类型进行参数类型检查时,并不检查数组的长度。例如:
void putValues( int[ 10 ] ); // 视为 int*
int main() {
int i, j[ 2 ];
putValues( &i ); // ok: &i 是 int*; 潜在的运行错误
putValues( j ); // ok: j 被转换成第 0 个元素的指针
// 实参类型为 int*: 潜在的运行错误
return 0;
}
参数的类型检查只能保证putValues()的两次调用都提供了int*型的实参,类型检查不能检验实参是一个 10元素的数组 。习惯上, C风格字符串是字符的数组,它用一个空字符编码作为结尾。但是所有其他类型,包括希望处理内含空字符的字符数组必须以某种方式在向函数传递实参时使其知道它的长度。
一种常见的机制是提供一个含有数组长度的额外参数。例如:
void putValues( int[], int size );
int main() {
int i, j[ 2 ];
putValues( &i, 1 );
putValues( j, 2 );
return 0;
}
另外一种机制是将参数声明为数组的引用
当参数是一个数组类型的引用时,数组长度成为参数和实参类型的一部分,编译器检查数组实参的长度与在函数参数类型中指定的长度是否匹配。
// 参数为 10 个 int 的数组
// parameter is a reference to an array of 10 ints
void putValues( int (&arr)[10] );//不能写成&arr[10],因为下标操作符的优先级较高
int main() {
int i, j[ 2 ];
putValues( i ); // 错误: 实参不是 10 个 int 的数组
putValues( j ); // 错误: 实参不是 10 个 int 的数组
return 0;
}
[转]数组引用:C++ 数组做参数 深入分析的更多相关文章
- C++二维数组(指针)做参数
一.问题描述 使用C++编程过程中经常需要使用到二维数组,然而初级程序员在使用过程中经常会出错使程序崩溃.下面就二维指针的定义,初始化,以及二维指针做参数给出简单介绍. 1.二维数组的定义与初始化 在 ...
- 数组引用:C++ 数组做参数 深入分析
转载:https://blog.csdn.net/jiangxinyu/article/details/7767065 在 C++中,数组永远不会按值传递,它是传递第一个元素,准确地说是第 0个 的指 ...
- C++数组引用
C++数组引用 一.数组引用 C++数组的引用:引用即别名这样比指针传地址方便多了 形参中的(&a)[10]可以就看做a数组的别名,肯定要指定数组大小,如果没有后面的数组大小,天知道是变量还是 ...
- C++数组做参数
首先,看一下下面这段代码: void changearr(int a[],int n){ cout<<sizeof(a)<<endl; // 输出4}in ...
- C++ 中数组做参数的分析
C++ 中数组做参数的分析 1.数组降价问题? "数组引用"以避免"数组降阶",数组降阶是个讨厌的事,这在C语言中是个无法解决的问题,先看一段代码,了解什么是& ...
- C语言 函数理解(以数组做参数)
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> int run(int *p){ // ...
- 引用、数组引用与指针引用、内联函数inline、四种类型转换运算符
一.引用 (1).引用是给一个变量起别名 定义引用的一般格式:类型 &引用名 = 变量名: 例如:int a=1; int &b=a;// b是a的别名,因此a和b是同一个单元 ...
- perl 引用(数组和hash引用) --- perlreftut - Mark 的一个简单的'引用'教程 ---Understand References Today. --Mark Jason Dominus, Plover Systems (mjd-perl-ref+@plover.com)
https://blog.csdn.net/fangwei1235/article/details/8570886 首页 博客 学院 下载 论坛 APP 问答 商城 活动 VIP会员 招聘 ITeye ...
- js 数组引用 发现的问题
最近做项目时,要对返回的数据[保存在json数组中]做一次修改,但原数据要保留一次做备用.首先想到,原数据不动,用一个临时的变量来修改,大致模型就是这样: // 原始: a=[1,2,3,4,5,.. ...
随机推荐
- ubuntu安装体验
本文记录一下昨晚及今天安装ubuntu系统的过程及体验 2016年6月13日09:36:11 更新 今天才有发现原来自己有个没填的坑 = = 那次安乌班图后第一感觉是很好用,新鲜了好几天,但是很快,新 ...
- 《JavaScript Dom编程艺术》用例总结
页首HTML 代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...
- XML新手入门 创建构造良好的XML(2)
本文描述了构建良好的XML需要遵循的规则.作者详细介绍了构建XML需要考虑的元素,如何命名约定.正确的标记嵌套.属性规则.声明和实体,以及DTD和schema的验证,十分便于新手开始学习了解XML. ...
- PHP解决网站高流量高并发问题
首先,确认服务器硬件是否足够支持当前的流量. 普通的P4服务器一般最多能支持每天10万独立IP,如果访问量比这个还要大, 那么必须首先配置一台更高性能的专用服务器才能解决问题 ,否则怎么优化都不可能彻 ...
- FTP配置参数
格式 vsftpd.conf 的格式非常简单,每行要么是一个注释,要么是一个指令.注释行以#开始并被忽略掉.指令行格式如下: 配置项=参数值 很重要的一点是,这个格式里不存在任何空格. 默认的,每一个 ...
- Sublime Text 3 个人配置文件
{ "dpi_scale": 1.0, "draw_white_space": "selection", "fallback_en ...
- mini-httpd源码分析-mini-httpd.c
main函数分析: 一,参数设置: 读取命令行参数 配置文件参数 读取参数,设置对应的全局变量.主要参数有:配置文件:资源目录:进程ID文件:日志文件:字符集:主机名及端口号... 二,参数处理:重点 ...
- java学习:AWT组件和事件处理的笔记(1)--Frame
1.java的抽象窗口工具包(AWT)中包含了许多类来支持GUI设计2.AWT由java的java.awt包提供3.再进行GUI编程时,要理解:容器类(Container),组件(component) ...
- 【配置】如何配置Tp-link无线路由器作为无线交换机
最近刚装了电信天翼宽带,谁知道现在只能装光猫.你说一个4M带宽有必要用光猫么?装好之后问题来了,这个光猫很奇葩,只有一个以太网接口,确有内置有路由功能,也就是只有一个出口的路由器.现在问题来了:我想接 ...
- Win7 64 bit 激活工具
下载地址:http://www.3987.com/xiazai/1/18/35487.html 一键运行,重启就激活了,简洁方便!