C++(7-8章)笔记

2023-05-16

第七章 函数——C++的编程模块

7.1函数
1,函数如何返回值的?
答:函数通过将返回值复制到指定的cpu寄存器或内存单元中来将其返回。随后,调用程序将查看该内存单元。返回函数和调用函数必须就该内存单元中存储的数据的类型达成一致。函数原型将返回值类型告知调用程序,而函数定义命令被调用函数应返回什么类型的数据。
2,为什么需要原型?
答:原型描述了函数到编译器的接口,也就是说,它将函数返回值的类型(如果有的话)以及参数的类型和数量告诉编译器。
3,如果该函数不能修改形参中的数组该如何操作〉
   答:可以如下:void show_array(cons tint arr[],int n);
在加上const之后表示该数组无法再sho_array()被修改,但并不是表示该数组中的所有数都是常量。
C++将const int arr[]解释为const int *arr。因此该声明实际上是说,arr指向的是一个常量值。

第八章 函数探幽

8.1 C++内联函数
1,常规函数和内联函数之间的主要区别不在于编写方式,而是在于C++编译器如何将他们组合到程序中。
2,函数执行时内部的操作方式:
编译器执行到函数调用的指令时,程序将在函数调用后立即存储该指令的内存地址,并将函数参数复制到堆栈(为此保留的内存块),跳到标记函数起点的内存单元,执行函数代码(也许还需将返回值放入到寄存器中),然后跳回到地址被保存你的指令处。
C++内联函数提供了另一种选择。内联函数的编译代码与其他程序“内联”起来。也就是说,编译器将使用相应的函数代码替换函数调用。对于内联代码,程序无需跳到另一个位置处执行代码,然后再跳回来。因此,内联函数执行速度比常规函数稍快,但代价就是消耗更多的内存。如果程序在10个不同的地方调用了同一个内联函数,那程序将包括该函数的10个代码拷贝。
使用:在函数声明前加上关键字inline。函数定义前加上关键字inline。 内联函数不能递归。
8.2 引用变量
1,int rats = 100; int & rod = rats;
这表示rod引用了rats,这两个变量的地址是相同的。
与指针有所不同在于,指针可以先声明,再赋值。这个必须在初始化时就赋值。 且 rod只能被赋值一次。 引用通常用于函数里面。Rod = x+3; 这是错误的。
2,如果函数调用的参数不是左值或与相应的const引用参数的类型不匹配,则C++将创建类型正确的匿名变量,将函数调用的参数的值传递给该匿名变量,并让参数来引用该变量。
3,应尽可能的使用const。
8.2.4将引用用于结构。P233页
定义函数: const sysop & use(sysop &sysopref);
1,第一个调用函数演示:ues(looper); 该函数调用将结构体looper按引用传递给use()函数,使得sysopref成为了looper的别名。
2,第二个是将引用作为返回值,通常返回机制将返回值复制到临时存储区域中,随后调用程序将访问该区域。然而,返回引用意味着调用程序将直接访问返回值,而不需要拷贝。通常,引用将指向传递给函数的引用,因此调用函数实际上是直接访问自己的一个变量。例如,在这个例子中,sysopref是looper的引用,因此返回值是main()中的原始looper变量。请看下面一行代码:
copycat = use(looper);
如果函数use()返回一个结构,sysopref的内容将被复制到一个临时返回存储单元中,返回该临时返回存储单元的内容将被复制到copycast中。然而,由于use()返回一个指向looper的引用,在这种情况下,looper的内存将被直接复制到copycast中。这使得执行效率更高。
记住:返回引用的函数实际上是被引用的变量的别名。
3,该程序使用函数调用来访问结构的成员
cout << “ues(looper):”<<use(looper).used<<endl;
由于函数use()返回一个指向looper的引用,因此上述代码与下面等价:
use(looper);cout<<”use(looper)”<<looper.used<<endl;
表示法use(looper).used访问looper的成员used。如果该函数返回一个结构而不是指向结构的引用,则这些代码访问的将是looper的临时拷贝的used成员。
2,返回引用时需要主要的问题
1,应避免返回当函数终止时不再存在的内存单元引用。
2,可采用new来分配新的存储空间。
3,为何将const用于引用返回类型
1,它并不意味着结构体sysop本身为const,而只一位着你不能使用返回的引用来直接修改它指向的结构。如省掉const就有可能出现下面的代码:

Use(looper).used = 10;这会使设计中添加模糊特性。增加犯错机会。
8.3默认参数
1,在函数调用时,可省掉实参,从而省掉的形参采用默认值
2,在原型中声明:
char *left(const char *str, int n = 1);
3,必须从右向左添加默认值,也就是说,要为某个参数设置默认值,则必须为它右边的所有参数提供默认值。
8.4函数重载
1,必须参数数目或参数类型不同。
2,名称修饰:
C++如何跟踪每一个重载函数呢?它给这些函数指定了秘密身份。使用C++开发工具中的编译器编写和编译程序时,C++编译器将执行一些神奇的操作——名称修饰或名称矫正。他根据函数原型中指定的形参类型对每个函数名进行加密。如:
long MyFunctionFoo(int,float)。将被名称转换为不太好看的内部表示,来描述该接口,如下所示: ?MyFunctionFoo@@YAXH@Z
对原始名称进行的表面看来无意义的修饰将对参数数目和类型进行编码。
8.5函数模板
1,函数模板就是使用通用类型(可用具体类型int,float替换)来定义函数。
2,函数模板允许以仁义类型的方式来定义函数,例如:
template
void Swap(Any &a,Any &b)
{
Any tem; temp = a; a = b; b = temp;
}
第一行指出要建立一个模板,并将类型令名为Any。关键字template和class是必须的。除非可以使用关键字typename代替class。另外必须使用尖括号。类型名可以任意选择(这里为Any),只要遵守C++令名规则即可;模板并不创建任何函数,而只是告诉编译器如何定义函数。需要交换int的函数时,编译器将按模板模式创建这样的函数,并用int代替Any。
提示:如果需要多个将同一种算法用于不同类型的函数,请使用模板,如果不考虑向后兼容的问题,并愿意键入较长的单词,则声明类型参数时,应使用关键字typename而不使用class。
注意:函数模板不能缩短可执行程序,最终的代码不包括任何模板,而只包括了为程序生成的实际函数。模板的好处在于:生成多个函数定义更简单,更可靠。

8.5.1重载函数模板
1,如果我们定义了Swap的模板,可现在要对两个数组进行交换,我们又应该怎么操作呢?
我们可以重载他,定义void Swap(Any *a,Any *b,int n);这与重载函数有异曲同工之处。
8.5.2显式具体化
如果我们想当编译器找到与函数调用匹配的具体话定义时,将使用该定义,而不再寻找模板。
1,对于给定的函数名,可以有非模板函数,模板函数和显式具体化模板函数以及他们的重载版本。
显式具体化的原型和定义应该以template<>打头,并通过名称来指出类型。
具体化将覆盖常规模板,而非模板函数将覆盖具体化和常规模板。
下面为交换job结构的非模板函数,模板函数和具体化的原型

void Swap(job &,job &);///非模板

template<class Any> ///模板
void Swap(Any &,Any &);

template<>void Swap<job>(job &,job &);///显式具体化
template<>void Swap(job &,job &);///simpler form 同显式具体化

8.5.3实例化和具体化
1,语法:template void Swap(int,int);
实现了这种特性的编译器看到上述声明后,将使用Swap()模板生成一个使用int类型的实例。也就是说,该声明的意思是“使用Swap()模板生成int类型的函数定义”。(函数会有一个Swap函数)
与显式实例化不同的是,显式具体化使用下面两个等价的声明之一:

template<>void Swap(int &,int&);
template <>void Swap(int &,int &);

(显式具体化只会在程序中如果有调用到此显式才会定义这个函数)
注意:试图在同一个编程单元中使用同一种类型的显式实例和显式具体化将出错。
隐式实例化,显式实例化和显式具体化统称为具体化。他们的相同之处在于,他们表示的都是使用具体类型的函数定义,而不是通用描述。
8.5.4编译器选择使用哪个函数版本
1,编译器决定使用哪个函数,这个过程称为重载解析,
第一步:创建候选函数列表。其中包含与被调用函数的名称相同的函数和模板函数。
第二步:使用候选函数列表创建可行函数列表。这些都是参数数目正确的函数,为此有一个隐式转换序列,其中包括实参类型与相应的形参类型完全匹配的情况。例如,使用float参数的函数调用可以将该参数转换为double,从而与double形参匹配,而模板可以为float生成一个实例。
第三步:确定是否有最佳的可行函数。如果有,则使用它,否则该函数调用出错。
如何确定最佳:(最佳到最差顺序如下)
1,完全匹配,但常规函数优先于模板
2,提升转换(char转int)
3,标准转换(int转char)
4,用户定义的转换,如类声明中定义的转换。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++(7-8章)笔记 的相关文章

随机推荐

  • STM32学习记录——蜂鸣器

    一 准备材料 1 参考资料 STM32F103xCDE DS CH V5 pdf STM32中文参考手册 V10 pdf 2 器件准备 STM32 蜂鸣器 这里是一个接好三极管的蜂鸣器 xff0c 因为STM32输出的引脚电流不能驱动蜂鸣器
  • Vmware16 ubuntu18.04虚拟机无法连网的解决方法之一

    问题描述 vmware里ubuntu系统的超级块无意间被搞崩了 xff0c 快照没保存下来 xff0c 重装系统完了发现连不上网 xff0c 百度无数方法包括还原默认设置 共享主机网络给vmnent8 删除虚拟机网卡再添加等等全都没用 xf
  • VNC Viewer连接树莓派无法调整分辨率

    问题描述 使用VNC Viewer连接树莓派 xff0c 但分辨率太低 xff0c 修改树莓派本身的分辨率并reboot后依然是默认的低分辨率 解决方法 了解发现 xff0c raspi config修改的是树莓派的分辨率 xff0c 修改
  • ROS与MATLAB联合控制

    虚拟机的下载与使用 版本说明 xff1a Windows xff1a MATLAB2020b 43 VMWare Workstation 15 Player 虚拟机 xff1a Ubuntu18 04 43 ROS1 melodic 43
  • 正点原子-freeRTOS

    裸机与操作系统的区别 裸机与RTOS的区别 裸机是在一个while循环中执行任务 xff0c 只有执行完了上一个才能执行下一个 RTOS是将多任务分散开 xff0c 每个任务执行一个时间 xff0c 然后切换到下一个任务 1 操作系统可以实
  • python安装numpy、pandas

    python安装numpy pandas python3 span class token parameter variable m span pip span class token function install span numpy
  • Android Studio模拟器如何把语言设置为中文和设置中文输入法

    文章目录 Android Studio模拟器语言设置为中文Android Studio模拟器设置中文输入法Android Studio模拟器安装搜狗输入法下载搜狗输入法x86的输入法APK安装APK配置搜狗输入法 Android Studi
  • Top44:VNC服务器端安装及配置多用户启动-CentOS7.5 配置VNC服务-Linux服务器端配置可视化桌面连接

    CentOS7 5 配置VNC服务 思路流程1 列出可用环境组2 选择安装Xfce桌面3 创建一个用户 xff08 root用户不让连 xff0c 需开启配置 xff09 4 安装VNC Server5 创建初始配置并设置密码6 停止vnc
  • Mac 使用svn 报错:zsh:mac zsh: command not found: svn完整解决方案

    Mac 使用svn 报错 xff1a zsh xff1a mac zsh command not found svn完整解决方案 之前都是用的git xff0c 普遍也都是使用的git xff0c 但是为了应对各种项目 xff0c svn也
  • FreeRTOS数据类型和编程规范

    目录 数据类型 变量名 函数名 宏的名 数据类型 每个移植的版本都含有自己的portmacro h头文件 xff0c 里面定义了2个数据类型 TickType t FreeRTOS配置了一个周期性的时钟中断 xff1a Tick Inter
  • 软件工程考研复试速成 - 知识点精炼 - 背诵版

    针对于考研复试 软件工程 的面试问答 xff0c 一般都是抽查重点的概念问题 xff0c 所以本文对软件工程知识点进行重点的精炼 xff0c 力求节省准研究生们的复习时间 写这篇博客也是因为小编也在准备复试 xff0c 对学习的网课进行笔记
  • 如何将模型alembic与动画alembic相关联?

    在三维动画制作时 xff0c 许多制作部门需要同时进行 xff0c 当模型部门制作好模型之后会把publish好的模型分给材质 xff0c 动画 xff0c layout等部门同时进行制作 xff0c 有时候项目要求角色有不同的材质和UV
  • Cesium标注实体【Entity】增、删、改、查

    实体实例将多种形式的可视化聚合到一个高级对象中 它们可以手动创建并添加到 Viewer entities 或由数据源生成 xff0c 例如 CzmlDataSource 和 GeoJsonDataSource 一 Entity 增加 方法一
  • hdu1085(生成函数)

    题目 我终于会用对拍器了 xff0c 我总是不敢去尝试新事物 xff0c 去年就像学 xff0c 上网搜过几次资料 xff0c 感觉烦就放弃了 xff0c 但事实证明其实非常简单 xff0c 对于我未来的coding生活来说实在是大有裨益
  • sumo osmWebWizard.py不生成OSM.sumocfg

    osmWebWizard在确定地图范围和车辆数 xff0c 点击Generate Scenario选项后 生成文件只含有osm netccfg和osm polycfg xff0c 如图 xff1a 主要原因是 当前版本默认仅勾选Add Po
  • vue封装Axios

    Axios的封装 安装axios npm install axios span class token punctuation span span class token comment 安装axios span 引入 一般在项目的src目
  • docker学习笔记(一)—— ubuntu16.04下安装docker

    本文开发环境为Ubuntu 16 04 LTS 64位系统 xff0c 通过apt的docker官方源安装最新的Docker CE Community Edition xff0c 即Docker社区版 xff0c 是开发人员和小型团队的理想
  • Centos7 安装teamviewer

    需求 需要在centos7服务器上安装最新的centos7 一 前期准备 下载teamviewer安装包 xff1a teamviewer官网 使用xftp把下载的文件传到服务器对应的文件夹中 二 安装步骤 启动前准备环境 1 关闭防火墙
  • 字典序最大的子序列(维护单调栈)

    题意 xff1a 找到给出序列的字典序最大的子序列 思路 xff1a 维护单调栈即可 代码 xff1a span class token macro property span class token directive keyword i
  • C++(7-8章)笔记

    第七章 函数 C 43 43 的编程模块 7 xff0e 1函数 1 xff0c 函数如何返回值的 xff1f 答 xff1a 函数通过将返回值复制到指定的cpu寄存器或内存单元中来将其返回 随后 xff0c 调用程序将查看该内存单元 返回