C/C++教程

C++ 函数(一)参数传递/return语句/返回类型

本文主要是介绍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 数组形参

数组的两个特殊性质:

  1. 不能拷贝数组:无法值传递
  2. 使用数组时通常转化成指针:传递参数时,实际上传递的是指向数组首元素的指针

数组的大小对函数调用没影响

管理指针形参:(主要是长度问题)

一种方法是使用标记指定长度,只适用于C语言中类似C风格字符串,以空字符结束

所以更实用的是另外两种方法:

  1. 标准库函数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));
    
  2. 显式传递一个数组大小形参

    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 可变形参

处理不同数量的实参的函数:

  1. 如果所有实参的类型相同,可以传递标准库类型:initializer_list

  2. 不同则写可变参数模板

  3. 省略符(一般只用于与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语句/返回类型的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!