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 ...
随机推荐
- Java [leetcode 12] Integer to Roman
题目描述: Given an integer, convert it to a roman numeral. Input is guaranteed to be within the range fr ...
- 剑指Offer:连续子数组的最大和
题目: 输入一个整型数组, 数组里有正数也有负数. 数组中的一个或连续的多个整数组成一个子数组. 求所有子数组的和的最大值. 要求时间复杂度为O(n) #include <stdio.h> ...
- (5)jvm垃圾回收器相关垃圾回收算法
引用计数法[原理]--->引用计数器是经典的也是最古老的垃圾收集防范.--->实现原理:对于对象A,只要有任何一个对象引用A,则计数器加1.当引用失效时,计数器减1.只要对象A的计数器值为 ...
- servlet规范
Servlet规范 一个最基本的 Java Web 项目所需的 jar 包只需要一个 servlet-api.jar ,这个 jar 包中的类大部分都是接口,还有一些工具类,共有 2 个包,分别是 j ...
- colspan在浏览器中失效的问题
<table border=" style="border-collapse:collapse;"> <tr> <td>def< ...
- table点击一行显示下一行的特效
效果体验:http://sandbox.runjs.cn/show/rw4vq8zo <!doctype html> <html> <head> <meta ...
- POJ 1017 Packets
题意:有一些1×1, 2×2, 3×3, 4×4, 5×5, 6×6的货物,每个货物高度为h,把货物打包,每个包裹里可以装6×6×h,问最少几个包裹. 解法:6×6的直接放进去,5×5的空隙可以用1× ...
- 6、四大组件之二-Service初步
一.什么是Service 有些用时比较长得操作我们希望他在后台运行 ,不耽误我们当前的操作 . 这就引入了Service概念 . 常见的比如:访问网络 , 文件IO操作 , 大数据的数据库任务,播放音 ...
- LR 常见问题总结
问题1:Error: Two Way Communication Error: Function two_way_comm_post_message/two_way_comm_p ...
- 发送一个简单的HTTP GET请求并且取回响应。
string uri="http//www.baidu.com"; WebClient wc = new WebClient(); Console.WriteLine(" ...