IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++学习 八、函数 -> 正文阅读

[C++知识库]C++学习 八、函数

前言

本片继续学习C++,函数。

函数使用

函数是C++的基本编程模块,以便于程序的模块化和代码复用。

函数声明(函数原型)

要使用函数,首先要提供函数原型,即声明函数,格式为
TypeName FuncName (Parameters)

返回值类型 函数名 (参数列表)

函数原型为编译器提供了函数名,函数返回值类型,参数类型和数量,用以编译器检查和处理。下面是一个函数声明的例子:

int func1(int a, int b);

上面这个函数声明了一个fuc1函数,它依次接受两个int类型的参数,返回int类型。

函数声明中的参数名可以省略,上面的函数声明等价于:

int func1(int, int);

C++中,如果向函数传递了不同类型的参数(可转换),将强制转换为期望的类型;如果返回值与返回类型不相同(可转换),则强制转换为返回类型:

int func1(int a, int b) {
	return a + b;
}

std::cout << func1(2.2, 3.3);

上面调用函数的时候,func(2.2, 3.3)中的’a’=2, ‘b’=3, 返回值为5。

此外,C++允许不带返回值和没有参数的函数,使用void关键字标识:

int func2(void);
void func3(int);
void func4(); // 参数列表中的void可省略

函数定义

函数定义时,有返回值的函数,在定义时必须使用return返回一个值,不带返回值的函数原型则不能使用return

函数内部可以再定义其它变量,但这些局部变量在函数外部是不可见的,函数生命周期结束后,这些局部变量就会被销毁。

函数定义示例:

int func2(void) {
	int a;
	return a;
}

void func3(int a) {
	a *= 2;
}

注意:C++的函数返回值不能是数组和字符串,但可以是其它整数、浮点数、指针、结构体、对象等类型。(比较有趣的一点,虽然不能返回数组,但是可以把数组放到结构体或者对象里返回)

此外,函数声明和定义可以放在一起,此时函数调用必须放在定义的后面:

int func5(int a, int b) {
	int c = a + b;
	return c;
}

func5(2, 3);

此外,为了模块化,还是尽量把函数声明和定义分开。一般函数声明放在.h头文件,
定义放在.cpp源文件。

函数调用

在程序中,通过函数名和参数调用函数:

void main() {
	int x=2;
	int y=3;
	int sum;
	sum = func5(x, y);
}

调用函数的参数要与函数原型的参数个数相同,参数类型相同或者能够转换。调用带有返回值的函数时,可以使用变量把返回值保存下来。

函数参数,按值传递

C++中,调用函数的参数按值传递,参数以值的形式传到函数中。调用函数的参数叫实参,函数内部的参数叫形参。

传值

上面的程序sum = func5(x, y);中,x, y是实参,a, b是形参。
调用函数func5时,创建形参a, b,把实参x, y的值赋给形参a, b,然后在函数体中使用形参进行计算。由于函数只传递实参的值而非变量的地址给形参,因此修改形参并不会影响实参。

下面这个示例函数并不能交换实参的值:

int paramFunc1(int a, int b) {
	int temp = a;
	a = b;
	b = temp;
	
	return 1;
}

函数体中的创建的形参和变量都是局部变量,在函数结束后将自动销毁。因此,示例函数中,a,b,temp在离开paramFunc1后都被销毁。

传址

由于函数参数的传递实质都是传值,因此在函数体内修改形参不会影响函数外的实参。

然而,如果给函数传递的参数是一个地址(指针),虽然修改形参的值仍然不会改变实参的值,但修改形参指针指向的值,实参指针指向的值也会发生改变。(直接修改了内存空间的存储数据)。

下面这个示例函数能够将实参指向的值进行交换:

int paramFunc2(int* pa, int* pb) {
	int temp = *pa;
	*pa = *pb;
	*pb = temp;
	
	return 1; 
}

函数与数组

函数经常需要处理数组这样的复杂数据结构。

数组篇中提到,C++把数组名当作数组首元素的地址,并且可以通过指针处理数组。因此,函数的常见“传数组”方式,也是通过指针:

void arrayFunc1(int arr[], int n); // 数组表示法
void arrayFunc2(int* arr, int n); // 指针表示法

参数列表中的arr[], *arr实际上都在声明arr是int类型的指针。arr[]更侧重于强调arr是数组的首元素地址,*arr更侧重于强调arr是一个指针。还需要一个参数int n指出数组的长度。

注意:只有在函数的参数列表中,才有数组表示法arr[]

将数组地址作为参数传给函数,节省了拷贝数组元素的时间和内存,但可能造成原始数组数据的错误修改。以后会记录使用const关键字保护函数实参的方法。

函数与字符串

函数如果要传递字符串参数,有两种方法。第一种方法与数组类似,传递字符串的地址:

int strFunc1(char* str); // 指针表示法
int strFunc2(char str[]); // 数组表示法

C++认为char数组名,字符串常量,char指针都表示字符串的首字符地址,而碰到的第一个空字符是停止符,因此函数参数不需要指出字符串的长度。

第二种传参方法,就是使用C++的string类,这个就非常简单了:

int strFunc3(string str);

传string对象是传值的方式,不会影响实参。

函数与结构体

函数传递结构体参数与传递普通类型参数其实是相似的,都是按值传递。

比较重要的一点是,如果结构体中有比较大的数据(数组,字符串等),可以通过传结构体的指针来节省拷贝时间和内存,并使用间接成员运算符->获得成员:

struct myStruct {
	int a;
}

void structFunc(myStruct* st) {
	st->a = 1; 
	*st.a = 1; // equal
}

注意:传结构体的指针时,实参指向的结构体就能够被形参修改。

默认参数

C++中,函数可以设置默认参数,在函数声明时设置:

int newFunc(int a, int b, int threshold=5);

上面的函数,可以只提供参数a,b的值,而省略传递threshold的值,这样函数会使用threshold的默认值5,如果提供threshold的值,就会覆盖默认值。

注意1:函数声明时,带默认值参数的右边的参数必须都带参数值。下面的函数声明将报错:

// int newFunc(int a, int threshold=5, int b) // error!

注意2:函数声明和定义中,只有一个需要带默认值,两个都带默认值就会报错。建议只在函数声明时加入默认值。

注意3:即使函数带了默认值,仍然是根据参数个数从左往右一个一个传值的,不能跳过某个默认参数。

内联函数

内联函数是C++提高程序运行速度的一种方式。

程序运行时,操作系统把程序的二进制机器指令加载到计算机内存中运行,因此每条指令都有特定的内存地址。函数调用时,程序存储调用指令的地址,然后跳转到函数的内存地址,执行函数,然后跳回调用指令的位置。

关键字inline把函数设定为内联函数。内联函数在编译时,不会被编译成函数被调用的指令,而是直接把内联函数体嵌入到调用处,类似于把函数在嵌入处重写。因此,内联函数在运行时,没有一般函数的跳转操作。

因此,内联函数的运行速度比常规函数快,但是内存占用多。如果有10个地方使用了内联函数,那么这个程序就有10个内联函数的代码块。

一般把内联函数的声明与定义结合,放在.h文件里:

inline int newFunc2(int a, int b) {
	return a + b;
}

一般来说,功能简单(代码短),使用次数多的函数更适合作为内联函数;代码比较长,内含循环之类的就不适合。

此外,内联函数不能递归。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-02-04 10:51:31  更:2022-02-04 10:53:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:14:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码