第八章 函数探幽

  1、常规函数与内联函数的主要区别不在于编写方式,而在于C++编译器如何将它们组合到程序中。

  2、常规函数调用使程序跳到另外一个地址(函数地址),并在函数结束时返回,更详细的的实现过程:执行到函数调用指令时,程序将在函数调用后立即存储该指令的内存地址,并将函数参数复制到堆栈(为此保留的内存块),跳到标记函数起点的内存单元,执行函数代码(也许还需将返回值i放入寄存器)然后跳回到地址被保存的指令处。来回跳跃并记录跳跃位置意味着以前使用函数时,需要一定的开销。

  3、内联函数:编译器将使用相应的函数代码替换函数调用。对于内联代码,程序无需跳到另一个位置处执行代码,然后再跳回来。因此,内联函数的运行速度比常规函数稍快,但代价是需要占用更多的内存。

  4、要使用内联函数,必须采取下述措施之一:①再函数声明前加上关键字inline②再函数定义前加上关键字inline。通常的做法是省略原型,将整个定义放在本应提供原型的地方。

  5、程序员请求将函数作为内联函数时,编译器并不一定满足这种要求。而且。内联函数不能递归。

  6、引用变量的主要作用是用作函数的形参。

  7、可以创建指向rats的引

用和指针(如下),这样,表达式rodents和*prats都可以和rats互换,而表达式&rodents和prats都可以同&rats互换。

  int  rats=101;

  int &rodents=rats;

  int *prats=&rats;

  8、必须在声明引用或者const指针时进行初始化,指针可以先声明再赋值。

  9、不能通过赋值来设置引用!!

  int  rats=101;

  int &rodents=rats;// rodents引用的是rats。

  int b=50;

  rodents=b;// 这句话仅仅是将b的值赋给rodents!!rodents和rats的值都变成了50,同时, rodents和rats的地址相同,而与b的地址不同。

  10、如果想用引用作为函数形参,而又不想改变变量的值,则应使用常量引用(const int &a).

  11、如果实参与常量(const)引用参数不匹配,C++将生成临时变量。两种情况:①实参的类型正确,但不是可修改的左值(非左值)②实参的类型不正确,但可以转换为正确的类型。注:非左值包括字面常量和包含多项的表达式。

  12、如果声明将引用指定为const,C++将在必要时生成临时变量。这些临时变量只在函数调用期间存在,此后编译器便可以随意将其删除。实际上,对于形参为const引用的C++函数,如果实参不匹配,则其行为类似于按值传递,为确保原始数据不被修改,将使用临时变量来存储值。注:如果接受引用参数的函数的意图是修改作为参数传递的变量,则创建临时变量将阻止这种意图的实现。解决方法是禁止创建临时变量。

  13、如果函数调用的参数不是左值或与相应的const引用参数的类型不匹配,则C++将创建类型正确的临时匿名变量,将函数调用的参数的值传给该匿名变量,并让参数来引用该变量。

  14、应尽可能将引用形参声明为const。

  15、通常将返回的引用声明为const是最好的选择。

  16、通常,返回机制将返回值复制到临时存储区域中,随后调用程序将访问该区域的临时拷贝值。然而,返回引用意味着调用程序将直接访问返回值,而不需要拷贝。通常,返回的引用将指向传递给函数的引用,因此调用函数实际上是直接访问自己的一个变量。注:返回引用的函数实际上是被引用的变量的别名。

  17、应避免返回一个指向临时变量的引用或者指针!因为函数运行完后,临时变量将不再存在。为避免这种问题,最简单的方法是,返回一个作为参数传递给函数的引用。作为参数的引用将指向调用函数使用的数据,因此返回的引用也将指向这些数据。另一种方法是用new来分配新的存储空间,然后返回指向该内存空间的指针。

  18、将const用于引用返回类型,意味着:不能使用返回的引用来直接修改它指向的结构。

  19、可以将C-风格字符串,包括引号括起的字符串字面量、以空字符结尾的char数组或者指向char的指针变量,赋给string引用!!因为string类定义了一种char*到string的转换功能。

  20、使用引用参数(指针参数)的主要原因有两个:①可以修改调用函数中的数据对象。②通过传递引用而不是整个数据对象,可以提高程序的运行速度。

  21、对于形参如何使用的几点指导原则:①如果数据对象是数组,则只能使用指针。②如果数据对象是结构,使用引用或指针。③如果数据对象是类对象,则使用引用。

  22、如何设置默认值?必须通过函数原型!!对于带参数列表的函数,必须从右向左添加默认值。也就是说,要为某个参数设置默认值,必须为它右边的所有参数提供默认值。

  23、关于函数重载,编译器在检查函数特征标时,将把类型引用和类型本身视为同一个特征标。例如:int a(int x);与int a(int &x);cout<<a(x);参数x与这两个原型都匹配!!

  24、将非const值赋给const变量是合法的,反之则是非法的。

  25、仅当函数基本执行相同的任务,但使用不同形式的数据时,才应采用函数重载。

  26、模板并不创建任何函数,而只是告诉编译器如何定义函数。

  27、如果需要多个将同一种算法用于不同类型的函数,请使用模板。注:函数模板不能缩短执行程序!最终的代码不包含任何模板,而只是包含为程序生成的实际 函数。

  28、需要多个对不同类型使用同一种算法的函数时,可使用模板。不过,并非所有的类型都使用相同的算法。为满足这种需求,可以像重载常规函数定义那样重载模板定义。和常规函数重载语一样,被重载的模板的函数特征标必须不同。

  29、模板函数的具体化函数定义——显示具体化。当编译器找到与函数调用匹配的具体化定义后,将使用该定义,而不再寻找模板。

  ①对于给定的函数名,可以有非模板函数、模板函数和显式具体化模板函数以及它们的重载版本。

  ②显式具体化的原型和定义应以template<>打头,并通过名称来指出类型。

  ③具体化将覆盖常规模板,而非模板函数将覆盖具体化和常规函数。即:编译器在选择原型时,如果有多个原型,非模板版本将优先于显式具体化和模板版本,而显式具体化将优先于使用模板生成的版本。

  例子:

  ①非模板void swap(int &,int &);

  ②模板 template<class T>

     void swap(T &,T &);

  ③显式具体化 template<> void swap<int>(int &,int &);或者 template<> void swap(int &,int &);

  30、实例化:编译器使用模板为特定类型生成函数定义时,得到的是模板实例。比如有一个模板函数 template<class T>void swap(T &,T &);函数调用swap(i,j)导致编译器生成swap()的一个实例,该实例使用int类型。模板并非函数定义,但使用int的模板实例是函数定义。这种实例化方式被称为隐式实例化。显示实例化的格式为:template void swap<int>(int,int);编译器看到这种声明后,将使用swap模板生成一个使用int类型的实例。注:显示具体化和显示实例化不同。试图在同一个编程单元中使用同一个类型的显式实例和显式具体化将出错。

  31、隐式实例化、显式实例化和显式具体化统称为具体化。相同之处是:它们表示的都是使用具体类型的函数定义,而不是通用描述。

  32、对于函数重载、函数模板和函数模板重载,C++来决定为函数调用使用哪一个函数定义,尤其是有多个参数时。这个过程称为重载解析。

  33、重载解析将寻找最匹配的函数。如果只存在一个这样的函数,则选择它。如果存在多个这样的函数,但其中只有一个是非模板函数,则选择该函数;如果存在多个合适的函数,并且它们都为模板函数,但其中有一个函数比其他函数更具体,则选择该函数。如果有多个同样合适的非模板函数或者模板函数,但没有一个函数比其他函数更具体,则函数调用是不确定的,因此是错误的。

  

《C++ Primer Plus》读书笔记之六—函数探幽的更多相关文章

  1. C++ primer plus读书笔记——第8章 函数探幽

    第8章 函数探幽 1. 对于内联函数,编译器将使用相应的函数代码替换函数调用,程序无需跳到一个位置执行代码,再调回来.因此,内联函数的运行速度比常规函数稍快,但代价是需要占用更多内存. 2. 要使用内 ...

  2. 《C#图解教程》读书笔记之六:接口和转换

    本篇已收录至<C#图解教程>读书笔记目录贴,点击访问该目录可获取更多内容. 一.接口那点事儿 (1)什么是接口? 一组函数成员而未实现的引用类型.只有类和结构能实现接口. (2)从ICom ...

  3. C语言深度解剖读书笔记(6.函数的核心)

    对于本节的函数内容其实就没什么难点了,但是对于函数这节又涉及到了顺序点的问题,我觉得可以还是忽略吧. 本节知识点: 1.函数中的顺序点:f(k,k++);  这样的问题大多跟编译器有关,不要去刻意追求 ...

  4. 《C++ Primer》读书笔记 第一章

    读<C++ Primer>才知道,自己对C++知之甚少... 写个博客记录下自己C++的成长,只是读书笔记,不是对<C++ Primer>知识点的总结,而是对自己在书上看到的以 ...

  5. C++ Primer Plus读书笔记

    第五章 循环和关系表达式 1. 2.类别别名: (1)   #define FLOAT_POINTER float * FLOAT_POINTER pa, pb; 预处理器置换将该声明转换成  flo ...

  6. C++ Primer Plus读书笔记(八)函数探幽

    1.内联函数 inline int square(x) {return x*x} 2.引用变量 int& 中的& 不是地址运算符,就想定义指针时的char* 一样,int&指的 ...

  7. 《C++ Primer Plus》读书笔记之五—函数-C++的编程模块

    函数-C++的编程模块   1.C++对于返回值的类型有一定的限制:不能是数组,但可以是其他任何类型——整数.浮点数.指针,甚至可以是结构和对象(有趣的是,虽然C++函数不能直接返回数组,但可以将数组 ...

  8. C++ Primer Plus读书笔记(七)函数

    1.声明 void fun1(); //该声明在C中的意思是不指定参数,但是在C++中是指定参数为void void func2(...); //C++中不指定参数 2.函数参数为数组区间 STL有数 ...

  9. C++ primer plus读书笔记——第7章 函数——C++的编程模块

    第7章 函数--C++的编程模块 1. 函数的返回类型不能是数组,但可以是其他任何一种类型,甚至可以是结构和对象.有趣的是,C++函数不能直接返回数组,但可以将数组作为结构或对象的组成部分来返回. 2 ...

随机推荐

  1. Linux中终端和控制台的一些不成熟的理解

    首先声明,这仅仅是在下一些不成熟的想法.是通过看网上的一些资料和自己实践的一些心得,应该都是些很不成熟甚至是不太正确的想法.但是我还是想记录下来,算是一个心路历程吧.等以后成熟了,再来修改. 首先说一 ...

  2. java NIO系列教程2

    7.FileChannel Java NIO中的FileChannel是一个连接到文件的通道.可以通过文件通道读写文件. FileChannel无法设置为非阻塞模式,它总是运行在阻塞模式下. 打开Fi ...

  3. springMVC中ModelAndView学写笔记

    api介绍: 构造函数摘要 ModelAndView()           bean样式用法的默认构造函数:填充bean属性,而不是传递构造函数参数. ModelAndView(Object vie ...

  4. antlr提取代码注释

    1. 来由 为什么要写提取注释呢,起因是工作需要.弄这么个不太重要的功能点来讲,旨在抛砖引玉. 一般而言,大家使用antlr解析源代码的时候,不会关心注释和空格之类内容,默认会过滤掉,不会放到语法树里 ...

  5. VUE自定义指令生命周期,VUE生命周期

    一.自定义指令的生命周期 自定义指令有五个生命周期(也叫钩子函数),分别是 bind,inserted,update,componentUpdated,unbind bind:只调用一次,指令第一次绑 ...

  6. SpringMVC 使用 RESTful 架构实现 CRUD 操作

    软件152 余建强 源码下载:http://download.csdn.net/detail/qq_35318576/9826210 1 使用框架 SpringMVC.Maven.Ajax.JSTL. ...

  7. session中用户信息改变问题

    问题描述: 在web项目中,我们经常将用户登录信息放在session中用来做后续的权限判断等操作,但最近在项目中发现一个奇怪的现象,session中的用户信息和登录时的信息有了差异. 原因: 在后台代 ...

  8. 域名(Domain Name)

    是由一串用点分隔的名字组成的Internet上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置,地理上的域名,指代有行政自主权的一个地方区域). 域名是一个IP地址 ...

  9. npm run build之后生成的dist如何扔到服务器运行(npm run build之后如何本地运行)

    运行npm run build之后,会生成一个dist文件夹,里面的目录结构大概是这样的: 生成完的文件我们怎么来运行呢?直接在本地打开inde.html是无法运行的,打包的时候有提示: 构建文件应该 ...

  10. C#中解决Response.AddHeader("Content-Disposition", "attachment; filename=" + filename)下载文件时文件名乱码的问题

    问题:下载文件时文件名乱码怎么解决? 在C#写后台代码过程中,经常遇到下载文件出现文件名乱码的问题,在网上找了很多方法,总是存在浏览器不兼容的问题,当IE浏览器不乱码时,火狐浏览器就会乱码,后来经过反 ...