高分请教:函数对象在什么情况下会被内联展开?

yfd 2003-08-21 08:47:54
函数对象在什么情况下会被内联展开?
怎么确认函数对象被内联展开了?

C++ Primer中说到了一点,但是我的理解上还是比较模糊。
...全文
237 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
TianGuangZao 2003-09-15
  • 打赏
  • 举报
回复
不妨看看 Josée Lajoie and Stanley Lippman 发表在 C++ Report magazine 专栏上的文章:

http://www.cuj.com/documents/s=8003/cujcexp1809lippman/

chinapub 上有人翻译过来了,却不注明出处:

http://www.china-pub.com/computers/emook/0954/info.htm
firingme 2003-09-13
  • 打赏
  • 举报
回复
VC7.1做的优化已经很不错了…………

没必要这么计较了,关于代码生成方面的优化,总感觉应该交给编译器
zss6587 2003-09-08
  • 打赏
  • 举报
回复
对于 “virtual function 不能 inline” 的说法,我给一点自己的理解,有误之处,请各位指正。我先来总结一下,inline 得以实施的几个前提:

1)函数足够小。xx 大师说,经验上为 8 行代码。我想还应该加上:无耗时的循环操作,不抛出 异常 :)

2)函数的调用频度。听说和“代码膨胀与执行速度的比例”有关,这当然与编译器有关。

3)这个函数能够被正确决议。嘿嘿,不太严谨的解释是:该函数的调用地址(虚表中的索引)在编译期间能够确定下来(也就是说,编译器能够将其转化为 static function 来链接调用)。

4)或许还有更多,但我想不到了 :)

与这个问题相关的,最重要的算是第三点了,不管它是否为 virtual member function, 只要它能够在编译期间决议,那么 inline 就可以实施。

yisan 2003-09-08
  • 打赏
  • 举报
回复
sorry,我发现还有一些相关信息

The inline keyword tells the compiler that inline expansion is preferred. However, the compiler can create a separate instance of the function (instantiate) and create standard calling linkages instead of inserting the code inline. Two cases where this can happen are:

*Recursive functions.
*Functions that are referred to through a pointer elsewhere in the translation unit.
These reasons may interfere with inlining, as may others, at the discretion of the compiler; you should not depend on the inline specifier to cause a function to be inlined.

Note that for a function to be considered as a candidate for inlining, it must use the new-style function definition. Functions that are declared as inline, and that are not class member functions, have internal linkage unless otherwise specified.

As with normal functions, there is no defined order of evaluation of the arguments to an inline function. In fact, it could be different from the order in which the arguments are evaluated when passed using normal function call protocol.

The /Ob compiler optimization option helps to determine whether inline function expansion actually occurs.

yisan 2003-09-08
  • 打赏
  • 举报
回复
如果你用的是VC,可以使用__forceinline 强制编译器对函数进行inline。

Even with __forceinline, the compiler cannot inline code in all circumstances. The compiler cannot inline a function if:
*The function or its caller is compiled with /Ob0 (the default option for debug builds).
*The function and the caller use different types of exception handling (C++ exception handling in one, structured exception handling in the other).
*The function has a variable argument list.
*The function uses inline assembly, unless compiled with /Og, /Ox, /O1, or /O2.
*The function returns an unwindable object by value, when compiled with /GX, /EHs, or /EHa.
*The function receives an unwindable copy-constructed object passed by value, when compiled with /GX, /EHs,, or /EHa.
*The function is recursive and not accompanied by #pragma inline_recursion(on). With the pragma, recursive functions can be inlined to a default depth of eight calls. To change the inlining depth, use inline_depth pragma.
*The function is virtual and is called virtually. Direct calls to virtual functions can be inlined.
*The program takes the address of the function and the call is made via the pointer to the function. Direct calls to functions that have had their address taken can be inlined.
*The function is also marked with the naked __declspec modifier.

If the compiler cannot inline a function declared with __forceinline, it generates a level 1 warning (4714).

既然它会产生一个warning,那我们就可以利用它来判断了。我用的是VC 7.1,但没有进行测试,有兴趣的朋友不妨一试。
SnHnBn 2003-09-08
  • 打赏
  • 举报
回复
看到有很多人争论inline函数是否被展开,其实很大原因是因为有个错误的惯性思维,即认为这个函数要么被内联要么不被内联。事实上,根据编译器和代码的具体情况,某些位置函数将被内联,某些位置不被内联。
zss6587 2003-09-08
  • 打赏
  • 举报
回复
建议楼主查阅《C++ FAQ》,我想里面的答复一定能使你信服 :)
mahatma_cn 2003-09-08
  • 打赏
  • 举报
回复
函数对象在什么情况下会被内联展开?
--------------当程序员在函数申明中建议编译器做内联处理时,编译器会考虑我们的请求,注意,仅仅是考虑,到底内联还是不,要看编译器的了。虚拟函数不能申明为内联,因为内联在编译器编译时刻确定,而这恰好与虚拟函数相斥,虚拟函数不到call时是不知道到底this指针指向谁!

那么确认函数对象被内联展开了?--------没有必要知道!
leechildren 2003-09-07
  • 打赏
  • 举报
回复
刚才楼上说:
虚函数确实不能定义为内联,因为虚函数是动态执行的,所以在运行时刻才能决定
而内联是编译时刻决定展开的

我就写了一个简单的测试函数, 结果执行没有问题,请问是我理解错了, 还是别的什么原因?

#include <iostream>
#include <string>
using namespace std;


class A
{
public:
virtual void print()
{
cout << "This is a virtual inline fucntion" << endl;
}
};

int main()
{
A a;
a.print();

}

neubird 2003-09-04
  • 打赏
  • 举报
回复
这个没什么好议论的啊,编译器想怎样就怎样了,不同的编译器不一样
zss6587 2003-09-03
  • 打赏
  • 举报
回复
"另,引楼上所述,的确不能取其地址,如果有什么代码取内联函数的地址的话
那么这个函数就不会被展开
虚函数确实不能定义为内联,因为虚函数是动态执行的,所以在运行时刻才能决定
而内联是编译时刻决定展开的"

我觉得你有点臆测的味道,正确答案在两本书里面: <<C++ Programming Language>> << C++ FAQ>> 。我不是什么大师,有争议的问题还是由大师来回答吧 :)
madmars 2003-08-24
  • 打赏
  • 举报
回复
告诉你们吧
经过我多年的编程经验,这个问题一直也是在困扰着我
并不是像很多书上写的那样,
实际上可以展开的地方很多,但是我们却没有办法知道到底什么情况下无法展开
不过假如编译器没有展开inline 那将是和可怕的,反而会增加额外的开销
不过据我的 观察,vc已经将大多数的情况都展开优化,效率得到了相当的提高

另,引楼上所述,的确不能取其地址,如果有什么代码取内联函数的地址的话
那么这个函数就不会被展开
虚函数确实不能定义为内联,因为虚函数是动态执行的,所以在运行时刻才能决定
而内联是编译时刻决定展开的
tonybaobao 2003-08-24
  • 打赏
  • 举报
回复
inline只是建议编译器这么做,但具体怎么看待,还是要看编译器。所以写了inline,未必一定就是内联函数。不过一般内联函数的行数都很少,多了的话,编译器就当作普通函数了。
zss6587 2003-08-24
  • 打赏
  • 举报
回复
"不能取内联函数的地址?"
======================

我不同意这种说法。虽然是内联函数,但它的地址仍然可以取, 因为一个函数是否该展开,并不是运行过程来决定的,是程序被编译的过程中的"编译器行为"。如果你要取一个被定义为 "inline" 的函数的地址,那么在用这个地址进行函数调用的时候,这个内联函数就肯定不会展开。可以参考一下 <<C++ Programming Language>>, BS 解释得很清楚的。
solotony 2003-08-22
  • 打赏
  • 举报
回复
不能取内联函数的地址?
未必?


函数体不能有引起分支类型的语句:if, switch, ?:, for, while, do while, 函数调用
这个条件也太强了,if和函数调用应是可以的吧?
亮剑_ 2003-08-22
  • 打赏
  • 举报
回复
thanks
jyfcsdn 2003-08-22
  • 打赏
  • 举报
回复
不好意思,我说的内联应该是内联展开的意思
yjh1982 2003-08-22
  • 打赏
  • 举报
回复
编译器想展开就展开
Chrisma 2003-08-22
  • 打赏
  • 举报
回复
1.函数体不能有引起分支类型的语句:if, switch, ?:, for, while, do while, 函数调用
2.在调用内联函数之前,内联函数必须定义函数体
3.不能取内联函数的地址
4.成员函数不能定义为虚函数
参见华中科技大学出版的<C++程序设计实践教程>
solotony 2003-08-22
  • 打赏
  • 举报
回复
函数对象永远不会被展开,函数(不论成员函数还是非成员函数)是否展开由编译器决定.

即使函数展开,它与未展开的函数也是不可能在源代码一级分析.所以根据这一点
来优化算法,我认为不合适.
加载更多回复(5)

24,854

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧