【C++】第7章 函数 知识总结
来源:互联网 发布:洛克希德马丁公司知乎 编辑:程序博客网 时间:2024/06/01 09:14
《C++ Primer Plus》第7章知识点总结
简单的知识不再进行赘述
形参:函数头中用于接受传递值的变量
实参:传递给函数的值
使用C++函数,必须完成以下工作:
(1)提供函数定义
(2)提供函数原型
(3)调用函数
函数原型
当函数没有写在main函数前面,而是写在后面时,需要在main前面加上函数的原型,例如下面这个例子
#include <iostream>void cheers(int);//这就是原型double cube(double x);//这就是原型int main(){ using namespace std; cheers(5); cube(2); return 0;}void cheers(int n){ using namespace std; cout<<n<<endl;}double cube(double x){ return x*x*x;}
从这个例子可以看到,原型有两种写法,一种不提供变量名,只提供了参数类型,如void cheers(int);另一种提供变量名,如double cube(double x);原型确保以下几点:
(1)编译器正确处理函数返回值
(2)编译器检查使用的参数数目是否正确
(3)编译器检查使用的参数类型是否正确
函数和数组
#include <iostream>const int ArSize=8;int sum_arr(int arr[],int n);int main(){ using namespace std; int cookies[8]={1,2,4,8,16,32,64,128}; int sum=sum_arr(cookies,ArSize); cout<<sum<<endl; return 0;}int sum_arr(int arr[],int n){ int total=0; for(int i=0;i<n;i++) total=total+arr[i]; return total;}
这是一个最简单的例子函数如何使用指针来处理数组
首先,在大多数情况下,C++和C语言一样,也将数组名视为指针。C++将数组名解释为其第一个元素的地址
cookies==&cookies[0]
当然,该规则有一些例外:
(1)数组声明使用数组名来标记存储位置
(2)对数组名使用sizeof将得到整个数组的长度(以字节为单位),比如sizeof cookies的值为32,而sizeof arr的值为4。因为sizeof arr只是指针变量的长度
(3)将地址运算符&用于数组名时,将返回整个数组的地址
在上面的例子中,执行了下面的函数调用
int sum_arr(cookies,ArSize);
其中cookies是数组名,而根据c++规则,cookies是其第一个元素的地址,因此函数传递的是地址。由于数组的元素的类型为int,因此cookies的类型必须是int指针,即int*。这表明,正确的函数头应该是:
int sum_arr(int * arr,int n)
其中,int * arr替换了int arr[]。这证明两个函数头都是正确的,因为在C++中,当且仅当用于函数头或函数原型中,int *arr和int arr[]的含义才是相同的。它们都意味着arr是一个int指针。然而,数组表示法(int arr[])提醒用户,arr不仅指向int,还指向int数组的第一个int。
就目前而言,要牢记以下两个恒等式:
arr[i]==*(ar+i)
&arr[i]==ar+i
将指针(包括数组名)加1,实际上是加上了一个与指针指向的类型的长度(以字节为单位)相等的值。对于便利数组而言,使用指针加法和数组下标时等效的。
为将数组类型和元素数量告诉数组处理函数,请通过两个不同的参数来传递他们
void fillArray(int arr[],int size);
而不要试图使用方括号表示法来传递数组长度
void fillArray(int arr[size]);——这是错误的
指针和const
为防止函数无意中修改数组的内容,可在声明形参时使用关键字const
void show_array(const double ar[],int n);
该声明表明,指针ar指向的是常量数据。这意味着不能使用ar修改该数据,也就是说可以使用像ar[0]这样的值,但不能修改
我们可以用两种不同的方式将const关键字用于指针
第一种方法是让指针指向一个常量对象,这样可以防止使用该指针来修改所指向的值
第二种方法时将只做了本身声明为常量,这样可以放置改变指针指向的位置
下面来看几个例子
int age=39; const int *pt=&age; //该声明指出,pt指向一个const int(这里为39),因此不能使用pt来修改这个值 *pt+=1; cin>>*pt;//这两语句都不合法,因为不能使用pt来修改它所指向的值 *pt=20; age=20; //pt指向age,pt是const的,而age不是,因此不可以通过pt修改age的值但是可以直接通过age变量来修改age的值 const float g_earth=9.80; const float *pe=&g_earth; //这种情况下,既不能使用g_earth来修改值9.80,也不能使用pe来修改 const float g_moon=1.63; float *pm=&g_moon; //这种情况在c++中是非法的,因为如果将g_moon的地址赋给pm, //则可以使用pm来修改g_moon,这使得g_moon的const状态变得无效 int age=39; const int *pt=&age; //第二个声明中const只能防止修改pt指向的值(这里为39),而不能防止修改pt的值。 //也就是说可以将一个新地址赋给pt,如下 int sage=80; pt=&sage; //此时pt指向地址的值为80,但仍然不能使用pt来修改指针的值 int sloth=3; const int *ps=&sloth; int *const finger=&sloth; //这里仔细观察第二和第三个声明中关键字const位置的不同 //第二个声明中,不允许使用ps来修改sloth的值,但允许将ps指向另一个位置 //第三个声明中,finger只能指向sloth,但允许使用finger来修改sloth的值 //简而言之,finger和*ps都是const,而*finger和ps不是
函数和二维数组
假设存在下面的代码
int data[3][4]={{1,2,3,4},{5,6,7,8},{2,4,6,8}};
int total=sum(data,3);
那么sum()的原型是:int sum(int (*ar2)[4],int size);
因为data是一个数组名,该数组有3个元素。第一个元素本身是一个数组,有4个int值组成。因此data的类型是指向由4个int组成的数组的指针。下面这是另一种格式,含义一样,但可读性更强
int sum(int ar2[][4],int size);
由于指针类型指定了列数,因此sum()函数只能接受由4列组成的数组。但长度变量指定了行数,因此sum()对数组的函数没有限制
函数和C风格字符串
表示字符串的三种方式:
(1)char数组
(2)用引号括起来的字符串常量(也称字符串字面值)
(3)被设置为字符串的地址的char指针
将字符串作为参数来传递,实际传递的是字符串第一个字符的地址。这意味着字符串函数原型应将其表示字符串的形参声明为char*类型。
C风格字符串与常规char数组之间的一个重要区别是,字符串有内置的结束字符(包含字符,但不以空值字符结尾的char数组只是数组,不是字符串)
下面这里个例子演示如何返回C风格字符串的函数
#include <iostream>const int ArSize=8;char *buildstr(char c,int n);int main(){ using namespace std; int times; char ch; cout<<"Enter a character: "; cin>>ch; cout<<"Enter an integer: "; cin>>times; char *ps=buildstr(ch,times); cout<<ps<<endl; delete [] ps;//free memory ps=buildstr('+',20); cout<<ps<<"-DONE-"<<ps<<endl; delete [] ps;//free memory return 0;}char *buildstr(char c,int n){ //要创建包含n个字符的字符串,需要能存储n+1个字符的空间,以便能存储空值字符 char *pstr=new char[n+1]; pstr[n]='\0'; while(n-->0) pstr[n]=c; return pstr;}
函数和结构
传递结构的地址而不是整个结构可以节省时间和空间。传递结构的地址时,由于形参是指针而不是结构,因此应间接成员运算符(->)而不是成员运算符(句点)。另外,做修改时不用返回一个结构体,可以直接对地址上的数据进行修改
函数指针
与数据项相似,函数也有地址。函数的地址是存储其机器语言代码的内存的开始地址
获取函数的地址
只要使用函数名即可,也就是说,如果think()是一个函数,则think就是这个函数的地址
声明函数指针
声明指向某种数据类型的指针时,必须指定指针指向的类型。同样,声明指向函数的指针时,也必须指定指针指向的函数类型。这意味着声明应指定函数的返回类型以及函数的特征标(参数列表)。也就是说,声明应像函数原型那样指出有关函数的信息。例如,一个估算时间的函数原型如下:
double pam(int);
则正确的指针类型声明如下:
double (*pf)(int);
这与pam()声明类似,这是将pam替换为了(*pf)。由于pam是函数,因此(*pf)也是函数,pf就是函数指针
使用指针来调用函数
只需要把(*pf)看作函数名即可
- 【C++】第7章 函数 知识总结
- 【C++】第1-2章 C++基础 知识总结
- 【C++】第3章 处理数据 知识总结
- 【C++】第4章 复合类型 知识总结
- 【C++】第5章 循环和关系表达式 知识总结
- 第5.6.7章linux知识总结
- 第二章 函数知识总结
- c primer plus第9章总结:函数
- 【C++】第8章 函数探幽 知识点总结
- 【C++】第6章 分支语句和逻辑运算符 知识总结
- 【计算机网络】第1章 概述 知识总结
- 【计算机网络】第2章 物理层 知识总结
- C语言第四章重要知识总结
- C语言第五章重要知识总结
- C语言第六章重要知识总结
- C语言第七章重要知识总结
- C一些知识总结
- C一些知识总结
- 动态分配---栈--堆分配
- Dijkstra--畅通工程续
- forward 和redirect的区别
- poj3480 反NIM游戏
- javascript实现图片左右移动动画
- 【C++】第7章 函数 知识总结
- 机器学习笔记六
- imageLoaderutil类
- java中this关键字的作用
- scrapy 下载图片 ImagesPipeline
- 160个练手CrackMe-005
- 装机教程
- 《MyBatis技术原理与实战》之SqlSession的用途
- 数据库_MySQL_由浅入深理解索引的实现