C++ 函数(一)参数传递/return语句/返回类型
2021/9/29 22:11:43
本文主要是介绍C++ 函数(一)参数传递/return语句/返回类型,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
C++ 函数(一)参数传递/return语句/返回类型
6.1 基础
函数的返回值不能是数组或函数类型,但可以是指向数组或函数的指针
6.1.1 作用域,局部对象
函数体是一个块,构成一个新的作用域,其中定义的变量和形参都是局部变量
在函数体外部定义的对象存在于程序的整个执行过程中
自动对象:
只存在于块执行期间的对象,例如形参,函数终止,形参会被销毁,局部变量如果本身不带初始值,则会执行默认初始化,意味内置类型的未初始化局部变量将产生未定义的值
局部静态对象
定义为static类型,如果没有显式的初始值,则将初始化为0
函数声明
又叫函数原型,不包含函数体,无需形参名(也可以有)
6.2 参数的传递
pass by value
将实参的值拷贝后赋值给形参,对形参的操作不会影响实参
指针形参
传递指针,拷贝的是指针的值,拷贝后的两个指针是不同的指针,但是由于指针可以间接的访问所指的对象,所以可以通过指针修改它所指的对象值
void reset(int *p){ *p = 0;//改变了指向的对象的值 p = 0;//只改变了p的局部拷贝,实参未改变 }
C++建议用引用类型的形参代替指针
pass by reference
void reset(int &p){}
改变引用形参,就是改变初始化形参的实参
尽量使用引用来避免拷贝,而且有些类不支持拷贝(比如IO类)
6.2.2 const形参,const实参
顶层const作用于对象本身,形参有顶层const时,传递常量或非常量对象都可以(实参初始化形参时会忽略顶层const)
void func(const int n){} const int i = 1; int j = 2; func(i); func(j); //上面两种调用方法都正确 //由于这种忽略,导致下面两种函数其实是一样的,所以不是重载 void func(const int i); void func(int i);
6.2.3 指针,引用形参
可以使用非常量初始化一个底层const,但是不能反过来,一个普通的引用必须用同类型的对象初始化
int i = 0; const int ci = i; string::size_type ctr = 0; reset(&i);//形参类型为int* reset(ci);//错误,不能使用const int对象的指针去初始化int* reset(i);//形参为int&时 reset(ci);//不能将普通引用绑定到const对象ci上 reset(42);//不能绑定字面值 reset(ctr);//类型不匹配,ctr是无符号类型
可以使用字面值初始化常量引用
尽量使用常量引用,避免限制函数能接收的实参类型(字面值)
6.2.4 数组形参
数组的两个特殊性质:
- 不能拷贝数组:无法值传递
- 使用数组时通常转化成指针:传递参数时,实际上传递的是指向数组首元素的指针
数组的大小对函数调用没影响
管理指针形参:(主要是长度问题)
一种方法是使用标记指定长度,只适用于C语言中类似C风格字符串,以空字符结束
所以更实用的是另外两种方法:
-
标准库函数begin,end
void print(const int *beg,const int *end){ while(beg!=end){ cout<<*beg++<<endl; } } int j[2] = {0,1}; print(begin(j),end(j));
-
显式传递一个数组大小形参
print(j,end(j)-begin(j));
数组引用形参/const形参
不需要改变数组元素值时,最好加上const
//数组的引用,维度是类型的一部分 void print(int (&arr)[10]){} //必须加(),否则arr就是引用的数组,而不是具有10个整数的整型数组的引用 //传递参数时,只能将函数作用域大小为10的数组 int i[2] = {2,1}; print(i);//错误
多维数组
C++的多维数组就是数组的数组
数组的数组,首元素本身就是一个数组,第二维不能省略
void print(int (*matrix)[10],int rowsize); //如果没有(),则是十个指针构成的数组,而不是指向含有10个整数的数组的指针 void print(int matrix[][10],int rowsize);
6.2.5 main(int argc,char *argv[])
6.2.6 可变形参
处理不同数量的实参的函数:
-
如果所有实参的类型相同,可以传递标准库类型:initializer_list
-
不同则写可变参数模板
-
省略符(一般只用于与C函数交互的接口程序)
形式:
void fun(parm_list,...)
void fun(...)
仅用于C和C++通用的类型
initializer_list对象中的元素永远是常量值
拷贝,赋值一个initializer_list对象不会拷贝列表中的元素,拷贝后原始列表和副本共享元素
list2(list1);//拷贝 list2 = list1;//赋值 void error_msg(initializer_list<string> il){ //initializer_list有begin,end,所以可以使用指针,范围for循环遍历列表 } //调用:expected,actuall为string对象 error_msg({"functionX",expected,actuall});
6.3 返回值 (return)
无返回值的return后可以什么都没有,也可以跟另外一个返回void的函数
不要返回局部对象的引用或指针
函数结束后,局部变量的内存空间会被释放
const string&manip(){//下面两个都错 string ret; if(){ return ret;//局部对象 } else{ return "empty";//临时局部变量 } }
引用返回左值:
调用运算符优先级和点,箭头相同
//符合左结合律,返回指针,引用,类的对象: auto s = func(s1,s2).size();
调用返回引用的函数会得到左值,其他类型为右值
因此这种情况下函数的返回值可以像使用其他左值一样:
char &get_val(string &str,string::size_type ix){ return str[ix]; } int main() { string s("a value"); get_val(s,0) = 'A'; //s[0]被改为A return 0; } //返回值是个常量引用就不能赋值了
列表初始化返回值
vector<string>pro(){ return {"one","two"}; }
如果返回内置类型则{}中最多包含一个值
返回数组指针
数组不能拷贝,所以函数不能返回数组
使用类型别名简化返回数组的指针和引用
//下面两行代码是等价的 typedef int arr[10]; using arr = int[10]; //返回一个指向含有十个整数的数组的指针 arr* func(int i); //如果不使用类型别名: Type (*function(parameter_list))[dimension] int (*func(parameter_list))[10]; //必须有*之外的(),否则声明的函数返回类型就会是指针的数组,而不是数组的指针
尾置返回:
函数真正的返回类型在形参列表之后,格式:
auto func(int i)->int(*)[10]; //任何函数定义都能使用尾置返回
decltype
如果知道函数返回的指针指向哪个数组,则可以使用decltype
int o[] = {12,3}; int o2[] = {1,2}; decltype(o)* arrptr(int i){}
decltype的结果是数组,所以还要加上*
这篇关于C++ 函数(一)参数传递/return语句/返回类型的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-15PingCAP 黄东旭参与 CCF 秀湖会议,共探开源教育未来
- 2024-05-13PingCAP 戴涛:构建面向未来的金融核心系统
- 2024-05-09flutter3.x_macos桌面os实战
- 2024-05-09Rust中的并发性:Sync 和 Send Traits
- 2024-05-08使用Ollama和OpenWebUI在CPU上玩转Meta Llama3-8B
- 2024-05-08完工标准(DoD)与验收条件(AC)究竟有什么不同?
- 2024-05-084万 star 的 NocoDB 在 sealos 上一键起,轻松把数据库编程智能表格
- 2024-05-08Mac 版Stable Diffusion WebUI的安装
- 2024-05-08解锁CodeGeeX智能问答中3项独有的隐藏技能
- 2024-05-08RAG算法优化+新增代码仓库支持,CodeGeeX的@repo功能效果提升