const形参和实参
当形参是const时,必须要注意关于顶层const的讨论。如前所述,顶层const的作用于对象本身:
const int ci=42; //不能改变ci,const是顶层的
int i=ci; //正确:当拷贝ci时,忽略了它的顶层const
int *const p=&i; //const是顶层的,不能给p赋值
*p=0; //正确:通过p改变对象的内容是允许的,现在i变成了0
和其他初始化过程一样,当用实参初始化形参时会忽略掉顶层const。换句话说,形参的顶层const被忽略掉了。当形参有顶层const时,传给它的常量对象或者非常量对象都是可以的:
void fcn(const int i){ /*fcn能够读取i,但是不能向i写值*/}
调用fcn函数时,既可以传入const int也可以传入int。忽略掉形参的顶层const可以产生意想不到的结果:
void fcn(const int i) {/*fcn能够读取i,但是不能向i写值*/}
void fcn(int i) {/*....*/}//错误:重复定义了fdn(int)
在C++语言中,允许我们定义若干具有相同名字的函数,不过前提是不同函数的形参列表应该有明显的区别。因为顶层const被忽略了,所以在上面的代码中传入两个fcn函数的参数可以完全一样。因此第二个fcn是错误的,尽管形式上由差异,但实际上它的形参和第一个fcn的形参没什么不同。
指针或引用形参与const
形参的初始化方式和变量的初始化方式是一样的,所以回顾通用的初始化规则有助于理解下面的知识。我们可以使用非常量初始化一个底层的const对象,但是反过来不行;同时一个普通的引用必须用同类型的对象初始化。
int i=42;
const int *cp=&i; //正确:但是cp不能改变i
const int &r=i; //正确:但是r不能改变i
const int &r2=42; //正确
int *p=cp; //错误:p的类型和cp的类型不匹配
int &r3=r; //错误:r3的类型和r的类型不匹配
int &r4=42; //错误:不能用字面值初始化一个非常量引用
将同样的初始化规则应用到参数传递上可得如下形式:
int i=0;
const int ci=i;
string::size_type ctr=0;
void reset(int &i);
reset(&i); //调用形参类型是int *的reset函数
reset(&ci); //错误:不能用指向const int对象的指针初始化int *
reset(i); //调用参数类型是int&的reset函数
reset(ci); //错误:不能把普通引用绑定到const对象ci上
reset(42); //错误:不能把普通引用绑定到字面值上
reset(ctr); //错误:类型不匹配,ctr是无符号类型
//find_char的第一个形参是对常量的引用
find_char("hello world",'o',ctr);//可以绑定到字面值常量上
要想调用引用版本的reset,只能使用int类型的对象,而不能使用字面值、求值结果为int的表达式、需要转换的对象或者const int类型的对象。类似的,要想调用指针版本的reset只能使用int*。
另一方面,我们能传递一个字符串字面值作为find_char的第一个实参,这是因为改函数的引用形参是常量引用,而C++允许我们用字面值初始化常量引用。
尽量使用常量引用
把函数不会改变的形参定义成(普通的)引用是一种比较常见的错误,这么做带来给函数的调用者一种误导,即函数可以修改它的实参的值。此外,使用引用而非常量引用也会极大地限制函数所能接受的实参类型。就像刚刚看到的,我们不能把const对象、字面值或者需要类型转换的对象传递给普通的引用形参。
const形参和实参的更多相关文章
- 关于函数传参的其他问题(const形参实参/可变形参)
const 形参和实参 当形参是 const 变量时,实参是 const 或者不是 const 变量都可以. 实参初始化形参时会忽略掉顶层 const: void gel(const int a){ ...
- C语言之形参和实参
一 形参与实参 1).定义 形参:形式参数. 就是定义函数的时候,写在函数名小括号后面的参数叫形参 实参:实际参数. 就是调用函数的时候,调用函数时写在函数名小括号后面的参数就叫实参 2).注意项 a ...
- const形参与非const形参
在程序设计中我们会经常调用函数,调用函数就会涉及参数的问题,那么在形参列表中const形参与非const形参对传递过来的实参有什么要求呢? 先来看一个简单的例子: #include <iostr ...
- c++形参改变实参(对指针的理解
这几天搞逻辑比较晕,居然把指针的概念都混淆了. eg:int *p;//当然不对指针初始化在有些编译器是通不过编译的,比如VS(尤其是选中了SDL) 指针p是一个对象,定义开始没有分配了内存空间,只是 ...
- C#形参,实参,值传递参数,引用传递参数,输出参数,参数数组的学习
1)形参 形参顾名思义就是形式上的参数,不是实际的参数,它代替实际传入方法的值.在方法体代码中代表了值本身参与运算.形参定义于参数中,它不同于方法体内局部变量,因为是一个变量,在它的作用域内不允许存在 ...
- c++形参和实参同名时,如何单步执行观察形参的变化。
c++形参和实参同名时,如何单步执行观察形参的变化? 方法:当程序运行到函数中时,添加变量观察即可.
- 关于Java中形参与实参的理解
今天阅读了一个写的非常棒的博文,通过此博文再次复习了Java中参数传递的知识(即值传递与引用传递的区别).参考网站http://www.cnblogs.com/binyue/p/3862276.htm ...
- JavaScript中函数的形参和实参的实现原理剖析
我们都知道JS里面参数的传递是可以不一样的,比如我们有一个函数: <script type="text/javascript"> function one(a,b,c) ...
- [C++程序设计]有关形参与实参,及返回值说明
有关形参与实参的说明:(1) 在定义函数时指定的形参,在未出现函数调用 时,它们并不占内存中的存储单元,因此称它们是 形式参数或虚拟参数,表示它们并不是实际存在的数据,只有在发生函数调用时,函数max ...
随机推荐
- ajax检测账户是否存在
Register.cshtml <div title="账户"> 账户 <input type="text" name="Acc_a ...
- 经典SQL语句大全_主外键_约束
一.基础(建表.建约束.关系) 约束(Constraint)是Microsoft SQL Server 提供的自动保持数据库完整性的一种方法,定义了可输入表或表的单个列中的数据的限制条件(有关数据完整 ...
- (转载)内联函数inline和宏定义
(转载)http://blog.csdn.net/chdhust/article/details/8036233 内联函数inline和宏定义 内联函数的优越性: 一:inline定义的类的内联函 ...
- MFC 状态栏相关使用(CStatusBar & CStatusBarCtrl)
原文:MFC 状态栏相关使用(CStatusBar & CStatusBarCtrl),沙漠紫风铃 本文介绍了MFC中和状态栏相关的用法: 在MFC的的单文档应用中,在建好应用程序之后,CMa ...
- [转] ArcEngine中打开各种数据源(WorkSpace)的连接
原文 ArcEngine中打开各种数据源(WorkSpace)的连接(SDE.personal/File.ShapeFile.CAD数据.影像图.影像数据集) ArcEngine 可以接受多种数据源. ...
- 理解Android的手势识别
对于触摸屏,其原生的消息无非按下.抬起.移动这几种,我们只需要简单重载onTouch或者设置触摸侦听器setOnTouchListener即可进行处理.不过,为了提高我们的APP的用户体验,有时候我们 ...
- 【译】 AWK教程指南 2概述
2.1 为什么用AWK 由于awk具有上述特色,在问题处理的过程中,可轻易使用awk来撰写一些小工具:这些小工具并非用来解决整个大问题,它们只扮演解决个别问题过程的某些角色,可通过Shell所提供的p ...
- Objective-C之消息机制
话说2014年4月编程语言排行榜中Objective-C的使用比又增加了,看来IOS和MAX OS的开发者是真给力呀. 不过个人感觉用不了多久,IOS和Android的开发者收入就不会有那么大的差异了 ...
- usb 驱动
usb 驱动学习总结: usb 采用分层的拓扑结构,金字塔型,最多是7层.usb 是主从结构,主和主或者从和从之间不能交换数据.理论上一个usb主控制器最多可接127个设备,协议规定每个usb设备具有 ...
- CI支持各种文件上传-文件类型(Linux + window)
$mimes = array( 'hqx' => 'application/mac-binhex40', 'cpt' => 'application/mac-compactpro', 'c ...