C++实用经验(五)

C++实用经验(五)

  • 禁止函数返回局部变量的引用
  • 函数传值、传指针和传引用的效率分析
    • 效率分析
  • 内联函数会像宏一样替换吗
  • 函数重载需要考虑什么
  • 不要让main返回void
  • 如何降低函数的圈复杂度

声明:以下内容总结自《C++程序员不可不知的101条实用经验》

禁止函数返回局部变量的引用

函数被调用时的操作:编译器首先把函数的输入/输出参数放到堆栈,指令寄存器IP放到堆栈(作为函数返回出口地址),然后是基址寄存器,接着是函数的局部变量。当函数返回时执行弹出操作,顺序正好和放到堆栈的顺序相反(首先释放堆栈中的局部存储变量,然后时基址寄存器、IP寄存器地址和函数的输入/输出参数),同时把放到堆栈的IP寄存器地址作为函数的出口地址并退出函数。

当函数内部的局部变量在堆栈上的内存被操作系统收回,则返回的局部变量具体变成什么就无法确定了。

解决方法:在函数内使用new生成对象,返回对象的指针或引用。
缺点:(1)函数内部申请了内存,但不负责释放内存,容易造成内存泄漏,增加用户使用负担。
(2)内存申请和释放不在一个模块中,影响模块的完整性和单一性,破坏函数内聚性。
(3)如果编写的程序作为一个库的形式提供给别人调用,别人不知道你在函数中申请了内存而不去释放内存。违反了谁创建,谁释放的原则。

函数传值、传指针和传引用的效率分析

传值:(1)在拷贝传值时,如果数据类型为类,函数会调用类的拷贝构造函数。
(2)在堆栈释放副本时,如果数据类型为类,函数会调用类的析构函数。

传引用:(1)堆栈上放的是引用的地址,在函数内通过自动的间接寻址找到引用内容。
(2)在副本创建和释放时不会发生构造和析构函数调用。

传指针:(1)指针是地址,传递时不会调用类的构造函数。
(2)指针的解引用就是间接寻址,获得指针变量中内存地址处的数据。

效率分析

(1)从执行效率(在被调用的函数体内执行时的效率)上说,传值调用时,对值的读写都是通过直接寻址的方式执行的,而指针和大多数情况下的引用是以间接寻址的方式执行,所以执行效率会低。如果对参数读写操作比较频繁,则传值比传指针、传引用的执行效率更高。
(2)从整个函数的执行角度考虑,传值调用时的值占用内存空间大,则拷贝需要较大的开销,造成效率低下。
(3)传值调用时,如果值的形参是父类,而实参是子类,则值传递时临时对象构造只会构造父类的部分,不会构造子类的任何特有部分。
(4)值传递比指针传递要安全,因为你不可能传一个不存在的值给传值参数或引用参数,而指针可能传一个不存在的地址。所以值传递和引用传递比指针传递要安全,使得代码更加健壮。

内联函数会像宏一样替换吗

内联函数是真正的函数,具备宏的效果,会像宏一样展开,使得调用内联函数时不用进行跳转,减小普通函数执行时保存现场和恢复现场时的开销,提高函数执行效率。
在类中直接定义成员函数,则成员函数为内联函数,称为隐式内联。
在类外单独定义成员函数,并在函数名前加上inline关键字,称为显式内联。
C++实用经验(五)_第1张图片
建议用内联函数替换宏。

C++实用经验(五)_第2张图片
C++实用经验(五)_第3张图片

函数重载需要考虑什么

函数重载:在同一作用域内可以有一组具有相同函数名、不同参数列表的函数。
C++实用经验(五)_第4张图片
重载的同名函数经过编译之后名称就变了,全局重载函数名称变化机制映射关系为:作用域+返回类型+函数名+参数列表
C++实用经验(五)_第5张图片

不要让main返回void

main函数的返回值说明程序的退出状态。返回0代表main函数成功执行完毕,程序正常退出,否则代表程序异常退出。

void main()这种形式的main函数不符合C++标准,不应该这样写。只用两种main函数定义方式是合法和正确的:
int main(void); int main(int argc, char *argv[]);

如果main函数执行结束时没有return语句,编译器会默认隐式地为程序添加return 0
注意点:(1)main函数返回类型必须为int (2)main最后加上return 0

如何降低函数的圈复杂度

圈复杂度:衡量一个模块判断结构的复杂程度,数量上表现为独立现行路径的条数,即合理地预防错误所需测试的最少路径条数。

圈复杂度高说明代码质量低且难以测试维护。

C++实用经验(五)_第6张图片
降低圈复杂度的9种技术(https://www.jianshu.com/p/c2e1e304cab2):
(1)提炼函数。把堆在一起的代码构建成模块化的函数。
(2)替换算法。
(3)分节条件表达式。
(4)合并条件式。
(5)合并重复的条件片段。
(6)移除控制标记。
(7)将查询函数和修改函数分离。
(8)令函数携带参数。
(9)以明确的函数取代参数。

你可能感兴趣的:(C++)