以下是《C++ Primer Plus》中第七章的内容:

使用C++函数的3个步骤:

提供函数定义

提供函数原型

调用函数

7.1.1 定义函数

函数分成两类:没有返回值的函数、有返回值的函数。

return返回语句标记了函数的结尾;否则,函数将在右花括号处结束。

对于有返回值的函数,必须使用返回语句,以便将值返回给被调用函数。

C++对于返回值的类型有一定的限制:不能是数组,但可以是其他任何类型。

7.1.2 函数原型和函数调用

为什么需要函数原型:原型描述了函数到编译器的接口,也就是说,它将函数返回值的类型以及参数的类型和数量告诉编译器。其次,函数完成计算后,将返回值放置在指定的位置——可能是CPU寄存器、也可能是内存中。然后调用函数将从这个位置获取返回值。原型指出了该函数的类型为double,因此编译器指导应检索多少个字节以及如何解释它们。

编译器需要原型,这样也可以提高效率。

原型的语法:函数原型是一条语句,因此必须以分号结束。原型不需要提供变量名,有类型列表就足够了。C++中原型是必不可少的。

原型的功能:原型可以帮助编译器完成许多工作;它可以极大地降低程序出错的几率。编译阶段进行的原型化被称为静态类型检查

========================================

7.2 函数参数和按值传递

接收传递值的变量被称为形参;传递给函数的值被称为实参

C++标准使用参数(argument)来表示实参,使用参量(parameter)来表示形参。参数传递将参数传递给参量。形参是实参的副本。

函数声明中的函数变量(包括参数)是函数私有的。在函数被调用时,计算机将为这些变量分配内存。函数结束时,计算机将释放这些变量使用的内存。这样的变量被称为局部变量,因为它们被限制在函数中。这样有助于确保数据的完整性。这样的变量也被称为自动变量,因为它们在程序执行过程中是自动被分配和释放的。

7.2.1 多个参数

函数可以有多个参数,只需使用逗号将这些参数分开即可。

只需添加分号就可得到该函数的原型;

提供变量名将使原型更易于理解。

7.2.2 另外一个接受两个参数的函数

=====================================================  

7.3 函数和数组

函数是处理更复杂的类型的关键。

7.3.1 函数如何使用指针来处理数组

C++和C语言一样,也将数组名视为指针。C++将数组名解释为其第一个元素的地址。

有个例外:使用取址运算符&用于数组名时,将返回整个数组的地址。

int * arr == int arr [ ];

指针也可以用方括号表示法来访问数组元素。

记住:指针加1,实际上是加上了一个与指针指向的类型的长度相等的值。

对于遍历数组而言,使用指针加法和数组下标时等效的。

7.3.2 将数组作为参数意味着什么

实际上并没有把数组的内容传递给函数,而是将数组的位置信息,长度,包含元素种类告诉了函数。函数便可使用原来的数组。传递的值是数组的地址。将数组地址作为参数可以节省复制整个数组所需的时间和内存。但是使用原始数据增加了破坏数据的风险。但是ANSI C和C++中的const限定符提供了解决这种问题的办法。

7.3.3 更多数组函数示例

构思程序时将:存储属性对数据的操作结合起来。

7.3.4 使用数组区间的函数

传统的C/C++方法处理数组的函数是:将指向数组起始处的指针作为一个参数,将数组长度作为第二个参数,这样便给函数提供了找到所有数据所需的信息。

另一种给函数提供所需信息的方法:即指定元素区间。可以通过传递两个指针来完成。一个指针标识数组的开头,一个指针标识数组的尾部。

end – begin 是一个整数值,等于数组的元素数目。

7.3.5 指针和const

有两种将const和指针结合使用的方法:

让指针指向一个常量对象:可以防止使用该指针来修改所指向的值。(指针指向的值)

int age =39;

const int * pt = &age;

微妙的地方是,pt的声明并不意味着它指向的值实际上就是一个常量。而只是对pt而言,这个值是常量。age不是const,可以直接通过age变量来修改age的值。

将指针本身声明为常量:可以防止修改指针指向的位置。(指针的值)

int * const finger = &sloth;

将指针作为函数参数来传递时,可以使用指向const的指针来保护数据。

====================================================

7.4 函数和二维数组

将二维数组作为参数的函数:

int sum(int ar2[ ] [4], int size);

int sum(int (* ar2)[4], int size);

====================================================

7.5 函数和C-风格字符串

C风格字符串由一系列字符组成:以空字符结尾,有关设计数组函数的知识也适用于字符串函数。

7.5.1 将C-风格字符串作为参数的函数

表示字符串的方式有3种:

char数组;用引号括起来的字符串常量;备设置为字符串的地址的char指针;

但上述3种选择的类型都是char指针,因此可以将其作为字符串处理函数的函数;

将字符串作为参数来传递,但实际传递的是字符串的第一个字符的地址。字符串函数原型应将其表示字符串的形参声明为char *类型

C风格字符串与常规char数组之间的一个重要区别:字符串有内置的结束字符。这意味着不必将字符串长度作为参数传递给函数。而函数可以使用循环依次检查字符串中的每个字符,直到遇到结尾的空值字符为止。

7.5.2 返回C-风格字符串的函数

函数无法返回一个字符串,但是可以返回字符串的地址,这样做效率更高。

====================================================

7.6 函数和结构

为结构编写函数比为数组编写函数要简单得多。结构变量的行为更接近于基本的单值变量。

注意:结构名只是结构的名称,要获得结构的地址,必须使用地址运算符&

使用结构编程时,最直接的方式是像处理基本类型那样来处理结构;将结构作为参数传递,并在需要时将结构用作返回值使用。

按值传递结构有一个缺点。如果结构非常大,则复制结构将增加内存要求,降低系统运行的速度。处于这些原因,许多程序员倾向于传递结构的地址,然后使用指针来访问结构的内容。

还有第三种选择:按引用传递

7.6.1 传递和返回结构

7.6.2 另一个处理结构的函数示例

7.6.3 传递结构的地址

传递结构的地址而不是整个结构以节省时间和空间,使用指向结构的指针。

注意点

调用函数时,将结构的地址(&pplace)而不是结构本身(pplace)传递给它。

将形参声明为指向polar的指针,即polar *类型。由于函数不应该修改结构,因此使用了const修饰符。

由于形参是指针而不是结构,因此应使用间接成员运算符(->),而不是成员运算符(句点)

====================================================

7.7 函数和string对象

功能上C风格字符串与string对象的用途几乎相同。但是string对象与结构更相似。例如:可以将一个结构赋给另一个结构,也可以将一个对象赋给另一个对象。可以将结构作为完整的实体传递给函数,也可以将对象作为完整的实体传递给函数。如果需要多个字符串,可以声明一个string对象数组。

====================================================

7.8 函数与array对象

按值传递对象给函数,函数处理的是原始对象的副本。

也可以传递指向对象的指针,这让函数能够操作原始对象。(修改对象,按地址传递)

按值传递(拷贝副本)、占用内存空间;

传递地址;但是代码看起来更复杂;

引用传递;-->解决了效率和表示法两方面的问题;

====================================================

7.9 递归

函数调用自己,被称为递归。

7.9.1 包含一个递归调用的递归

7.9.2 包含多个递归调用的递归

====================================================

7.10 函数指针

函数也有地址,函数的地址是存储器机器语言代码的内存的开始地址。通常这个地址对用户而言既不重要也没有什么用处。对程序而言,却很有用,可以编写将另一个函数的地址作为参数的函数。

7.10.1 函数指针的基础知识

获取函数地址;

函数名及函数的地址;

声明函数指针;

声明应该像函数原型那样指出有关函数的信息。

double pam(int);  //函数的prototype

double (*pf)(int);  //声明指向函数的指针,包含指向函数的返回类型、函数的特征标;

使用函数指针来调用函数;

对于(*pf),只需将它看做是函数名即可。

double pam(int);

double (*pf)(int);  //声明函数指针

pf =pam;   //将pam函数赋给pf函数指针,

double x = pam(4);

double y =(*pf)(5);  //这种格式虽然不太好看,但是给出了强有力的提示,代码正在使用函数指针

double y = pf(5);  //这个格式就和函数差不多;

7.10.2 函数指针示例

7.10.3 深入探讨函数指针

7.10.4 使用typedef进行简化

关键字typedef让您能够创建类型别名;

使用typedef可减少输入量,让您编写代码时不容易犯错。

例子:

typedef const double *(*p_fun)(const double *, int);   //p_fun现在就是函数指针,或者可以认为是一种类型

p_fun p1 = f1;   //现在p1是指向f1的函数指针

====================================================

7.11 总结

函数是C++的编程模块。要使用函数,必须提供定义和原型,并调用该函数。函数定义是实现函数功能的代码;函数原型描述了函数的接口:传递给函数的值的数目和种类以及函数的返回类型;函数调用使得程序将参数传递给函数,并执行函数的代码。

在默认情况下,C++函数按值传递参数。这意味着函数定义中的形参是新的变量,它们被初始化为函数调用所提供的值。C++函数通过使用拷贝,保护了原始数据的完整性。

C++将数组名参数视为数组第一个元素的地址。从技术上讲,这仍然是按值传递的,因为指针是原始地址的拷贝,但函数将使用指针来访问原始数组的内容。当且仅当声明函数的形参时,下面两个声明才是等价的。

typename arr[ ];

typename * arr;

C++提供了3中表示C-风格字符串的方法:字符数组、字符串常量、字符串指针;它们的类型都是char *;

C++提供了string类,用于表示字符串。

C++处理结构的方式与基本类型完全相同,这意味着可以按值传递结构,并将其用作函数返回类型。

C++函数可以是递归的;

C++函数名与函数地址作用相同。

C++_函数1-编程的基本模块函数的更多相关文章

  1. Python_oldboy_自动化运维之路_函数,装饰器,模块,包(六)

    本节内容 上节内容回顾(函数) 装饰器 模块 包 1.上节内容回顾(函数) 函数 1.为什么要用函数? 使用函数之模块化程序设计,定义一个函数就相当于定义了一个工具,需要用的话直接拿过来调用.不使用模 ...

  2. Python笔记_第四篇_高阶编程_再议装饰器和再议内置函数

    1. 概述: 我们在前面用了很多的装饰器这个工具的方法.这个位置要系统的讲一下装饰器. 1.2 为什么需要装饰器. 装饰器本质是一个Python函数,它可以让其他函数在不需要任何代码变动的前提下增加额 ...

  3. Python黑帽编程2.6 模块

    Python黑帽编程2.6 模块 我们已经学习了如何在你的程序中定义一次函数而重用代码.如果你想要在其他程序中重用很多函数,那么你该如何编写程序呢?你可能已经猜到了,答案是使用模块.模块基本上就是一个 ...

  4. Linux 编程中的API函数和系统调用的关系【转】

    转自:http://blog.chinaunix.net/uid-25968088-id-3426027.html 原文地址:Linux 编程中的API函数和系统调用的关系 作者:up哥小号 API: ...

  5. perl编程中的map函数示例

    转自:http://www.jbxue.com/article/14854.html 发布:脚本学堂/Perl  编辑:JB01   2013-12-20 10:20:01  [大 中 小] 本文介绍 ...

  6. VB 核心编程及通用模块开发 笔记1

    前言:学习任何编程语言.编程工具的目的不外乎解决生活问题,能够快速.高效解决问题的方式就是不错的方式,至于选择什么“工具”,众位看官看着办,本人虽然有过3年vb开发经验,但是一直没有深入学习,现已购买 ...

  7. Scala - 快速学习08 - 函数式编程:高阶函数

    函数式编程的崛起 函数式编程中的“值不可变性”避免了对公共的可变状态进行同步访问控制的复杂问题,能够较好满足分布式并行编程的需求,适应大数据时代的到来. 函数是第一等公民 可以作为实参传递给另外一个函 ...

  8. python_08 函数式编程、高阶函数、map、filter、reduce函数、内置函数

    函数式编程 编程方法论: 1.面向过程 找到解决问题的入口,按照一个固定的流程去模拟解决问题的流程 (1).搜索目标,用户输入(配偶要求),按照要求到数据结构内检索合适的任务 (2)表白,表白成功进入 ...

  9. Scala实战高手****第12课:Scala函数式编程进阶(匿名函数、高阶函数、函数类型推断、Currying)与Spark源码鉴赏

    /** * 函数式编程进阶: * 1.函数和变量一样作为Scala语言的一等公民,函数可以直接赋值给变量 * 2.函数更常用的方式是匿名函数,定义的时候只需要说明输入参数的类型和函数体即可,不需要名称 ...

随机推荐

  1. [luogu3391] 【模板】文艺平衡树(fhq-treap反转区间)

    解题关键:无旋treap模板. #include<iostream> #include<cstdio> #include<cstring> #include< ...

  2. Linux扩展根目录

    一.简介 使用linux系统的过程中,有时发现系统根目录(/)的空间不足,导致系统运行很慢,针对该现象,本文详细介绍根目录(/)的空间扩展方法.   二.操作步骤 1)查看根目录大小 df 2)查找系 ...

  3. Django框架 之 admin管理工具(组件使用)

    Django框架 之 admin管理工具(组件使用) 浏览目录 激活管理工具 使用管理工具 admin的定制 admin组件使用 Django 提供了基于 web 的管理工具. Django 自动管理 ...

  4. Entity Framework 6.0 Tutorials(1):Introduction

    以下系统文章为EF6.0知识的介绍,本章是第一篇 原文地址:http://www.entityframeworktutorial.net/entityframework6/introduction.a ...

  5. 【原创】boost::recursive_mutex请小心使用

    recursive_mutex会减少死锁几率?恩看上去的确如此,但是事实上呢?我们从BOOST的官方逻辑去理解: recursive_mutex类可多次进入锁,这样在递归时可以避免一次死锁的几率,这是 ...

  6. hdu 2519 新生晚会 (求排列组合时容易溢出)

    #include<stdio.h> #include<algorithm> using namespace std; void cal(int n,int m) { ; m=m ...

  7. 7.内网渗透之windows认证机制

    文章参考自三好学生域渗透系列文章 看了内网渗透第五篇文章,发现如果想要真正了解PTT,PTH攻击流程,还需要了解windows的认证机制,包括域内的kerberos协议. windows认证机制 在域 ...

  8. JQuery.validator插件使用

    首先给变量validator赋值 var validator =$('#test').validate({validate构造 }); 接着调用 $('#test').valid() 会使用上面的验证 ...

  9. Job-Show Liang,你来掌管诺基亚王国,可好?

    保留我一向高大上风格,开头当然来一个段子 在即将到来MWC(Mobile World Congress缩写,世界移动通信大会),很高兴能听到小诺来参展,我不得不给它32个赞,因为小诺已经好几届没有浮头 ...

  10. wp8 与wp7.5图标规格说明

    wp8 小图标 159*159 中图标 336*336 大图标 691*336 wp7.5 173*173