您的位置:首页 > 编程语言 > C语言/C++

C++ Primer Plus学习之函数篇二

2013-08-08 15:55 211 查看
问题一:关于内联函数(inline function)的种种细节

            首先,为什么要引入内联函数?在提出内联函数之前,如果一个函数体中调用了其他的函数(比如A调用了B),那么编译器在执行到A中的B时,会暂停A的执行,寄存器保存当前的执行地址,并产生一块内存区域,用来保存B的返回值。然后去寻找B函数,执行完B函数将结果保存在刚才产生的内存区域中。然后找到寄存器的执行地址,继续执行A的代码。这样来回跳跃并记录跳跃位置,需要一定的开销。

           因此提出了内联函数,在函数的声明处对其定义。这样编译器在编译时遇到该函数,并不会跳出来去寻找该函数,而是直接将该函数的代码嵌入到当前函数中,减少了开销。不过带来的副作用就是内存的开销,会占用更多的内存。因此在使用内联函数时一定要确保所使用的内联函数时比较小的。(貌似如果内联函数比较大,会默认的将内联函数替换成常规函数)。

           另外,内联函数不能执行递归。(why?)

           提到内联函 数,通常会和宏定义放在一起比较。宏定义只是常规的文本替换,和内联函数不同。并且使用宏定义的时候要非常的小心,对变量和函数体要加括号。比如:

                                 #define square(x)    x*x;          

                                 square(4+5)并不会返回81,而是4+ 5 * 4 + 5等于29

问题二:关于引用(&)

          引用是已定义的变量的别名。主要用在函数的形参中,这样函数将使用原始数据,而不是副本。好处是减少开销,可以像指针一样对原始数据进行修改。

          切记一点:引用必须在声明时对其初始化。

  

          如果一个函数的返回值是引用类型,会更高效一点,因为不会产生一个临时变量用来存储函数的返回值。直接返回的必须是一个引用变量(即函数的某个引用形参)。

          当然也可以在函数中new一块区域存储变量,使返回值返回这个变量。但是这样做很容易忘了delete这块new的区域。

         

          另外如果不需要改变引用变量的值,可以使用const来修饰引用类型的形参。

 

问题三:关于函数中的默认参数

          函数的实参赋值顺序是从左到右,函数的默认参数赋值则是从右到左。

          函数的默认参数设置必须通过函数原型。

 

问题四:关于函数重载和函数模板

          在函数重载中,将类型引用和类型本身视为同一种类型。例如:

                                double function(double x)             与              double function(double & x)相同

          函数模板使用泛型来定义函数。可以使用如下两种方式建立模板:

                        template <typename T>                           template<class T>

          模板中有一个概念“显示具体化”(explicit specialization)。在原版中是这样解释的:If the complier find a specialized definition that exactly matches a function's call,it ues the definition without looking for templates.也就是说如果存在显示具体化的原型,就不会再去寻找函数模板了。显示具体化优先于模板。

 

          那么,在这么多的函数重载,函数模板,函数模板重载中,编译器是如何选择合适的函数版本去执行需要的操作呢?

          基本流程如下:

                 1. 创建候选函数列表(选择函数名称相同的)

                 2. 使用候选列表创建可行函数列表(选择参数数目相同,参数类型可以隐式的转换成相同类型的)

                 3. 确定是否有最佳的选择,如果有,调用执行,否则报错。

          因此提出了一个最佳选择的概念,如何去衡量最佳?

                 1. 可以完全匹配。这种情况下如果既存在常规函数又存在函数模板,选择常规函数(参数为非const类型的函数优先于const修饰的函数)

                 2. 提升转换(如char可以隐式的转换成int)

                 3. 标准转换(如int转换为char)

                 4. 用户自定义转换(函数定义在使用之前,将忽略其他的函数模板) 

 

        C++11中提供了decltype(declare type)用来解决下面的问题:

                     template <class T1,class T2>

                    void  fun(T1 a,T2 b)

                   {

                           x = a + b;

                    }

         x为什么类型的?用decltype(a+b)x,编译器会明确x 的类型为a+b的类型。

        同时C++11还提供了auto fun(T1 a,T2 b)->decltype(a+b)来明确函数的返回类型。 

         

        

         
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ 函数 重载 模板 C++11