C++语言博大精深,当然在博大的同时就有复杂的出现,最突出的就是概念多不容易弄明白。本人也是初学C++在此谈点对一些概念的理解一来加深记忆,二来给各位看官做个参考。
文中我会以谭浩强教授的《C++面向对象程序设计》(《面》)和《C++Primer第三版》(《P》)为引用加以说明,在此请对国内编程语言教程有偏见的朋友积点口德。
首先请看《P》对inline函数提出的概念:inline函数给出了一种解决方案。若一个函数被指定为inline函数,则它将在程序中每个调用点上被“内联地”展开。
这个概念就引出了两个问题一个是解决方案另一个是内联地展开。
什么是解决方案呢?《P》中又对这一概念作出了解释:inline指示对编译器来说只是个建议。编译器可以选择和忽略该建议,因为把一个函数声明为inline函数,并不见得真的适合在调用点上展开。也就是说编译器对inline函数是有选择性的,并不是程序员对一个函数声明了inline,这个函数就必须是内联的了。
什么是内联地展开呢?《P》中对这个概念没有作出解释,《面》一书中有:程序调用inline函数时并不真正地执行函数的调用过程(如保留返回地址等处理),而是把函数代码嵌入程序地调用点。这样可以大大减少调用成员函数地时间开销。这里一个是对内联函数调用的说明“嵌入”,一个是对内联优点的说明“大大减少调用函数的时间开销”。嵌入也可以理解为替换,就像宏一样可以直接对变量进行替换处理,当编译器看见函数方法调用时,就用整个函数定义嵌入到函数方法调用的那个位置。例如:
遇见display();就用它的定义void display() { cout << "Hello World" << endl; }去替换。这样做就省去了函数调用所耗的时间。
当然程序员最关心的还是什么条件用内联函数什么条件不用。
《effectiveC++》作者指出inline函数不能滥用,更不能不用。但都没有作出最终建议,在这里我总结了几条建议供大家参考:
- 递归函数-不用
- 包含循环等控制结构的函数-不用
- 大于10行代码的函数(当然只对变量初始化的可以忽略)-不用
- 小的,只有几行代码的,经常调用的函数-可以用
当然这些并不是硬性规定,因为inline只是一种对编译器的建议,采用与否全看编译器对代码的理解。如果你坚持在包含循环控制的函数中声明inline,那编译器完全可以忽略你的建议。我们又何必自讨苦吃给编译器增加麻烦呢?
最后还应该注意两点:(1)内联函数的声明和定义需放在一个源代码文件中,也就是说不能让声明与实现一个在.h中一个在.cpp中。(2)类中成员函数都是隐式指示为内联函数,加inline和不加inline是一个意思。
以下是VC++2005优化页面中对inline的设置:
图中优化一项中除“禁用”外,其他O1、O2、OX三个选项都是对下图中“内联函数展开”默认为Ob2,也就是编译器自动选择代码中哪些函数需要进行lnline,并不是只有被程序员声明为inline函数的函数才内联。
如果你不需要编译器自动选择你可以在“内联函数展开”中选择Ob1,也就是只有程序员声明为inline的函数才内联。
当然就如上面提到的虽然你选择了Ob1但是编译器还是可以忽略掉你的inline声明。MSDN:编译器将内联展开选项和关键字视为建议。不保证函数将内联展开。无法强制编译器内联特定函数。
总结:简单的记住两点一个是内联函数只是一种对编译器的建议,既然是建议就有采纳和不采纳之分。再一个就是内联函数的运用可以加快程序运行速度,当然这个速度具体加快多少我不得而知,但是这并不妨碍我们去认识它和去运用它。