C++函数实用经验

文章内容均整理自    刘光《C++程序员不可不知的101条实用经验》

1.进制函数返回局部变量的引用
请谨记:
(1)函数返回时,保证返回数据超出函数范围后依然有效,如返回局部变量的引用就是禁止的
(2)函数返回时,返回new生成的对象也是不可取的,这样会使代码层次混乱,不能保证做到及时回收资源

2.函数传值,传指针及传引用的效率分析
(1)值传递
如果传值类型为类类型,函数会调用类的构造函数进行类对象构造和数据拷贝,释放时同样会调用类的析构函数进行类对象数据的释放
(2)引用传递
即使引用形参为类类型,也不会发生构造和析构函数的调用
(3)指针传递
即使指针形参为类类型,也不会发生构造和析构函数的调用,因为创建的不是类对象,而是类指针
三种传值方式的差异:
(1)值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟内存空间以存放有主调函数传进来的实参值。被调函数对形参的任何操作都作为局部变量进行,不会影响主调函数的实参的值。
(2)引用传递过程中,被调函数的形式参数也作为被调函数的局部变量在堆栈中开辟了内存空间,存放的是主调函数实参的地址。对形参做的任何改变都和影响实参。
(3)指针传递是传值调用的特例,传的值为主调函数变量的地址。被调函数的形式参数也作为被调函数的局部变量在堆栈中开辟了内存空间,对形参做的任何改变都和影响实参。

3.内联函数会像宏一样替换吗
注意:
(1)宏不能访问对象的私有成员,宏很容易引起二义性。内联函数是真正的函数,使用时会像宏一样展开。
(2)宏不进行参数检查而内联函数进行参数检查。
(3) 内联函数inline关键字必须和函数定义在一起才会有效,同时内联函数的代码函数不能太多。
(4) 在类内定义的成员函数称为隐式内联函数。类外定义的函数称为显示内联函数。
宏和内联函数的相同之处:
(1)都可以提升代码执行的效率
(2)都能代码展开的方式进行代码替换,减少函数调用的开销
(3)两者都适用于代码量较小的代码,若代码量较大,宏会减低程序执行速度,而内联函数会被当成普通函数使用
(4)都会发生代码拷贝,过多的使用会浪费内存空间
宏和内联函数的不同之处:
(1)宏使用容易出现二义性,而内联函数不会
(2)宏不进行参数安全检查,而内联函数会进行参数安全检查
(3)内联函数可以调式,宏定义不行

4.函数重载需要考虑些什么
函数重载:在同一作用域内,有一组具有相同函数名,不同参数列表的函数
注意:两个函数声明完全相同为重复声明,若仅有返回类型不同,则第二个函数声明错误
请谨记:
(1)合理利用重载函数会给程序可读性带来好处,但不合理的重载函数不但对代码可读性没有帮助,还会污染命名空间
(2)设计重载函数尽量避免多个函数满足同一个实参匹配,这样会导致重载匹配的二义性问题。

5.不要让main返回void
请谨记:
(1)在C/C++标准中,main函数的返回类型仅有int这种类型,不存在void或者其他类型
(2)某些编译器允许main函数返回void或其他类型,但这是不符合C++标准的,会出现移植性问题

6.尽量拒绝使用变参函数
简化的printf实现

#include <stdarg.h>

/* minprintf: minimal printf with variable argument list */

void minprintf(char *fmt, ...)

{

    va_list ap/* points to each unnamed arg in turn */

    char *p, *sval;

    int ival;

    double dval;

    va_start(ap, fmt)/* make ap point to 1st unnamed arg */

    for (p = fmt; *pp++) {

       if (*p != '%') {

           putchar(*p);

           continue;

       }

       switch (*++p) {

           case 'd':

              ival = va_arg(ap, int);

              printf("%d"ival);

              break;

           case 'f':

              dval = va_arg(apdouble);

              printf("%f"dval);

              break;

           case 's':

              for (sval = va_arg(apchar *); *svalsval++)

                  putchar(*sval);

              break;

           default:

              putchar(*p);

              break;

       }

    }

    va_end(ap)/* clean up when done */

}

拒绝使用原因:
(1)缺乏类型检查,省略号的本质就是告诉编译器关闭所有检查,有程序员接管,启动reinteroret_cast。
(2)由于禁用了语言类型检查功能,所以调用时必须通过其他方式告诉函数所传递参数的类型,以及参数的个数。这种方式需要手动完成,容易出错。
(3)可变参数不支持自定义类型,但自定义类型在C++中占有重要地位

7.如何降低函数的圈复杂度
简单的说,函数的圈复杂度就是统计一个函数由多少个分支(if,while,for等),如果没有分支的话其复杂度为1,每增加一个分支复杂度加1,无论这些分支是并列的还是嵌套的。一个函数的圈复杂度就相当于至少需要多少个测试用例才能对这个函数做到全路径覆盖。
计算方法:①由1开始计数,一直往下通过程序②一旦遇到关键字if,while,for等就加1③switch_case的每一种情况都加1
减低圈复杂度的思想就是尽可能将函数各功能模块分离开来,单独作为一个函数来使用。 实际使用推荐类函数重载多态机制降低函数圈复杂度。

































猜你喜欢

转载自blog.csdn.net/sinat_39061823/article/details/80569273