关于函数传参的其他问题(const形参实参/可变形参)
const 形参和实参
当形参是 const 变量时,实参是 const 或者不是 const 变量都可以。 实参初始化形参时会忽略掉顶层 const:
void gel(const int a){
;
}
void gel(int a){
;
}
//这两个gel函数的形参列表是等价的,因此会出现编译错误。
指针或引用形参与 const
#include <iostream>
using namespace std; void gel(int *a){
;
} void gel(int &a){
;
} int main(void){
int i = ;
const int ci = i;
string::size_type ctr = ;
gel(&i);//调用形参是int*的gel函数
// gel(&ci);//错误,不能忽略底层const,即不能用指向const int的指针初始化int*
gel(i);//调用形参是int&类型的gel函数
// gel(ci);//错误,不能把普通引用绑定到const对象ci上
// gel(1024);//错误,非常量引用不能绑定字面值
// gel(ctr);//错误,类型不匹配,ctr是无符号类型的
return ;
}
应该尽量使用常量引用避免将普通引用形参绑定到const 对象上的错误。
main 函数传参:
#include <iostream>
using namespace std; int main(int argc, char **argv){
cout << argc << endl;
for(int i = ; i < argc; i++){
cout << argv[i] << endl;
}
return ;
}

main 函数有两个形参,通常命名为 argc 和 argv,其中 argv 是一个字符串数组,而 argc 是字符串数组的长度。其中 argv[0] 保存该源文件生成的可执行文件的名字,使用 argv 中的实参时,可选实参时从 argv[1] 开始的。
含有可变形参的函数:
为了能编写能处理不同数量实参的函数,c++11 新标准提供了两种主要的方法:如果所有的实参类型相同,可以传递一个名为 initializer_list 的标准库类型,如果实参的类型不同,可以编写一种特殊的函数--可变参数模板。
c++ 还有一种特殊的形参类型--省略符 可以传递可变数量的实参。这种功能一般只用于与 C 函数交互的接口程序。
initializer_list 定义在 initializer_list 头文件中。它提供的操作有:
initializer_list<T> lst;//默认初始化,T类型元素的空列表
initializer_list<T> lst{a, b, c...};//lst 的元素和初始值一样多,lst 的元素是对应初始值的副本,列表中的元素是 const
lst2(lst);//拷贝或赋值一个 initializer_list 对象不会拷贝列表中的元素,拷贝后,原始列表和副本共享元素
lst2 = lst;
lst.size();//列表中元素的数量
lst.begin();//返回指向列表中首元素的指针
lst.end();//返回lst列表中的尾后指针
和 vector 一样,initializer_list 也是一种模板类型,定义 initializer_list 对象时,必须说明列表中所含元素的类型。
initializer_list<string> ls;//initializer_list 的元素类型时 string
initializer_list<int> li;//initializer_list 的元素类型时 int
如果时向 initializer_list 形参中传递一个值的序列,则必须把序列放在一对花括号内,且允许多次调用传递的参数数目不同:
#include <iostream>
#include <initializer_list>
using namespace std; void error_msg(initializer_list<string> li){
for(auto indx : li){
cout << indx << " ";
}
cout << endl;
} int main(void){
string s1, s2;
cin >> s1 >> s2;
if(s1 != s2) error_msg({"functionX", s1, s2});
else error_msg({"functionX", "okay"});
return ;
}
因为 initializer_list 包含 begin 和 end 成员,所以可以使用范围 for 循环。
对于含有 initializer_list 形参的函数,其形参列表是允许含有其他类型的形参的,而 initializer_list 形参中只能传指定类型的对象。
#include <iostream>
#include <initializer_list>
using namespace std; void error_msg(initializer_list<string> li, int cnt){
cout << cnt << ":" << endl;
for(auto indx : li){
cout << indx << " ";
}
cout << endl;
} int main(void){
string s1, s2;
cin >> s1 >> s2;
if(s1 != s2) error_msg({"functionX", s1, s2}, );
else error_msg({"functionX", "okay"}, );
return ;
}
省略符形参:
省略符形参是为了方便于 c++ 程序访问某些特殊的 c 代码而设置的,这些代码使用了名为 varargs 的 c 标准库功能。省略符形参应该仅仅用于 c 和 c++ 通用的类型,且大多数类型的对象在传递给省略符形参时都无法正确拷贝。
省略符形参只能出现在列表的最后一个位置,它的表现形式只有以下两种:
void gel(parm_list, ...);
void gel(...);
第一种形式指定了 gel 函数的部分形参类型,对应于这些形参的实参将会执行正确的类型检查。省略符形参所对应的实参类型无需类型检查。在第一种形式中,声明符后面的逗号是可选的。
#include <iostream>
#include <initializer_list>
using namespace std; void gel1(string, ...){} void gel2(string ...){}//省略string后面的逗号 void gel3(...){} void gel3(int a, int b){
cout << a << " " << b << endl;
} int main(void){
int a = , b = ;
string s1 = "jf", s2 = "jfk";
char ch1 = 'f', ch2 = 'j';
gel1(s1, a, b, ch1, ch2);
// gel1(a, a, a);//错误,指定了的形参会进行类型检查
gel2(s1, a, b);
// gel3(s1, a, b);//错误,string不是c和c++通用的类型
gel3(a, b, ch1, ch2);
gel3(a, b);//输出1 2.省略号的优先级别最低,所以在函数解析时,只有当其它所有的函数都无法调用时,编译器才会考虑调用省略号函数的。
return ;
}
关于函数传参的其他问题(const形参实参/可变形参)的更多相关文章
- python函数传参是传值还是传引用?
首先还是应该科普下函数参数传递机制,传值和传引用是什么意思? 函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题.基本的参数传递机制有两种:值传递和引用传 ...
- [Java]_函数传参的疑惑与思考
问题来源于leetcode上的两道题 Path Sum I && II,分别写了两个dfs. void dfs(TreeNode node , int sum , ArrayList& ...
- pytest十一:函数传参和 firture 传参数 request
为了提高代码的复用性,我们在写用例的时候,会用到函数,然后不同的用例去调用这个函数.比如登录操作,大部分的用例都会先登录,那就需要把登录单独抽出来写个函数,其它用例全部的调用这个登录函数就行.但是登录 ...
- 『Python × C++』函数传参机制学习以及对比
一.Python函数传参 在python中,函数传参实际上传入的是变量的别名,由于python内在的变量机制(名称和变量值相互独立),只要传入的变量不可变(tuple中的元素也要是不可变的才行),那么 ...
- 函数传参传的是啥的思考【java Python】
今天看<java 核心 卷1>的时候,作者提到了函数传参的问题,他提到,java传参,传的是值,而不是引用,然后,函数将要传的实参的值(如果实参是基本数据类型,那么就是值.如果实参是对象, ...
- JS——变量和函数的预解析、匿名函数、函数传参、return
JS解析过程分为两个阶段:编译阶段.执行阶段.在编译阶段会将函数function的声明和定义都提前,而将变量var的声明提前,并将var定义的变量赋值为undefined. 匿名函数: window. ...
- C#篇(三)——函数传参之引用类型和值类型
首先应该认清楚在C#中只有两种类型: 1.引用类型(任何称为"类"的类型) 2.值类型(结构或枚举) 先来认识一下引用类型和值类型的区别: 函数传参之引用类型: 1.先来一个简单的 ...
- pytest_函数传参和firture传参数request
前言为了提高代码的复用性,我们在写用例的时候,会用到函数,然后不同的用例去调用这个函数. 比如登录操作,大部分的用例都会先登录,那就需要把登录单独抽出来写个函数,其它用例全部的调用这个登陆函数就行. ...
- 函数传参和firture传参数request
前言 为了提高代码的复用性,我们在写用例的时候,会用到函数,然后不同的用例去调用这个函数.比如登录操作,大部分的用例都会先登录,那就需要把登录单独抽出来写个函数,其它用例全部的调用这个登陆函数就行.但 ...
随机推荐
- 小记一次mysql启动失败没有日志的处理
本来mysql好的,之前清理了一次tmp下的东西,mysql在查询的时候提示: Can't create/write to file '/tmp/ib0n3frL 然后停止启动: [root@sevc ...
- 新浪微博logo已经去掉了“新浪”二字
如果有一天我能做出一个产品,它的命名就以我所在的行业命名该多好啊,可惜那只是一个梦.但这样的梦新浪微博却实现了,今天我登陆新浪微博的时候发 现logo已经去掉了“新浪”二字,我开始还以为我自己的电脑网 ...
- printf 的格式
1) 类型类型字符用以表示输出数据的类型,其格式符和意义如下表所示: %c 输出单个字符 %s 输出字符串 %u 以十进制形式输出无符号整数 %d 以十进制形式输出带符号整数(正数不输出符号) ...
- java Web 请求servlet绘制验证码简单例子
主要用来了解java代码怎么绘制验证码图片,实际开发中不会这样用 protected void doGet(HttpServletRequest request, HttpServletRespons ...
- 一个由有符号下标引起的bug
先看段代码: if(s[d[i]]) { ... } 这里的d是一个char*的内存buffer,s是一个256长度的bool数组.上段代码逻辑是,s已进行过初始化,其作用是过滤字节,有些字节对应tr ...
- Redis安装文档
1.前置条件 前置条件:linux已经可以上网,参考:https://www.cnblogs.com/ZenoLiang/p/10201875.html 2.安装redis 2.1依赖包检查 1. ...
- 61-结点选择(树形dp)
http://lx.lanqiao.cn/problem.page?gpid=T14 算法训练 结点选择 时间限制:1.0s 内存限制:256.0MB 问题描述 有一棵 n 个 ...
- 解决在Python中使用Win32api报错的问题,No module named win32api
一.系统环境 操作系统: Win7 64位 Python:3.7.0 二.在使用import win32api时,报错:No module named win32api 网上查到有下面解决办法: 方法 ...
- GCC 常见参数配置
博客转载自:https://www.cnblogs.com/zhangsir6/articles/2956798.html 简介gcc and g++现在是gnu中最主要和最流行的c & c+ ...
- 3.Hive中查看数据来源文件和具体位置方法
虚拟列 -- 当 hive 产生了非预期的或 null 的时候,可以通过虚拟列进行诊断,判断哪行数据出现问题 INPUT__FILE__NAME (输入文件名)map任务读入File的全路径 ...