【longshanks请进】关于您在小弟我帖子中的inline回复(由于结贴时候么没看到)
【longshanks请进】关于您在我帖子中的inline回复(由于结贴时候么没看到)
是这样的,函数inline之后,并且编译器允许inline,那么,函数会整个地在调用位置就地展开。就仿佛没有调用函数一样。相比标准函数的调用,inline省去了函数调用时的栈操作,包括参数压栈、寄存器压栈、栈清理等等。并且,由于函数代码就地展开,编译器在优化时可以将inline函数代码和调用方代码作为一个整体考虑,进一步加以优化。这一点标准函数是做不到的。
需要强调的是,inline不是强制的。某些编译器可能会不执行inline。但现在主流的编译器,如g++、vc、bcb等等都积极地执行inline。即便如此,inline并非总是执行的,比如递归的函数,编译器就拒绝inline,因为这种inline是做不到的。
编译器对inline的支持如何,需要参考相关文档,或者做些实验。而且,通常在debug状态下,inline是不做的,只有release编译,才会执行。
所有类型的函数都可以标记成inline,包括全局函数、成员函数、static函数。对于直接定义在class或struct中的成员函数,默认inline。如果定义在class/struct外的,则必须要通过inline关键字指定:
class A
{
void f1() {...} //inline
void f2();
inline void f3();
};
void A::f2() {...} //非inline
inline void f3() {...} //inline
最后,inline有一个有趣的现象。考虑如下函数:
int a[100];
inline void fill_a(int v) {
if(v==0)
return;
a[v]=v*10;
fill_a(v-1);
}
fill_a(9);//希望inline展开
尽管使用了inline关键字,但编译器是不会inline的。但是,inline还是可以做到的:
template <int n>
struct fill_a
{
void operator()() {
a[n]=n*10;
fill_a <n-1> ()(); //递归
}
}
template <>
struct fill_a <0>
{
void operator()() {
a[0]=0;
}
}
fill_a <9> ()();
此时,fill_a <9> ()();编译后(优化打开)的代码可能是这样的(伪码):
a[9]=90;
a[8]=80;
...
a[0]=0;
这样,便实现了递归的inline。
=================================
很抱歉啊,在没看到您的回复之后我就已经结贴了,新在重新拿出来。请教几个小问题。
上面的代码我还真看不懂啊。为什么操作符后面带两个()()?还有想要看懂这样的代码需要参考什么资料啊。
template <int n>
struct fill_a
{
void operator()() {
a[n]=n*10;
fill_a <n-1> ()(); //递归
}
}
这个我懂。
可是下面这个:
template <>
struct fill_a <0>
{
void operator()() {
a[0]=0;
}
}
就不懂了。它是函数还是类?
------解决方案--------------------
template <>
struct fill_a <0>
{
void operator()() {
a[0]=0;
}
}
=======================
这个是类.
void operator()()是对函数调用操作符 operator()的重载.一个类重载了operator()
后, 其对象就可以象函数那样调用了. STL中的防函数, boost中的function等等都用
到这个特性.
fill_a <0> filla;
filla(); // 调用operator(), 看起来与一个函数调用没有区别.
上面的operator()重裁不带参数, 返回null.
假如有另一个重载如int operator()(int a, int b), 你就可以传参数
和接收返回值了.
int result = filla(a, b)
.................
------解决方案--------------------
【Ref】
函数对象概述
关 键 词:对象
阅读提示:函数对象是比函数更加通用的概念,因为函数对象可以定义跨越多次调用的可持久的部分(类似静态局部变量),同时又能够从对象的外面进行初始化和检查(和静态局部变量不同)。
顾名思义,就是在某种方式上表现得象一个函数的对象。典型地,它是指一个类的实例,这个类定义了应用操作符operator()。
函数对象是比函数更加通用的概念,因为函数对象可以定义跨越多次调用的可持久的部分(类似静态局部变量),同时又能够从对象的外面进行初始化和检查(和静态局部变量不同)。例如:
是这样的,函数inline之后,并且编译器允许inline,那么,函数会整个地在调用位置就地展开。就仿佛没有调用函数一样。相比标准函数的调用,inline省去了函数调用时的栈操作,包括参数压栈、寄存器压栈、栈清理等等。并且,由于函数代码就地展开,编译器在优化时可以将inline函数代码和调用方代码作为一个整体考虑,进一步加以优化。这一点标准函数是做不到的。
需要强调的是,inline不是强制的。某些编译器可能会不执行inline。但现在主流的编译器,如g++、vc、bcb等等都积极地执行inline。即便如此,inline并非总是执行的,比如递归的函数,编译器就拒绝inline,因为这种inline是做不到的。
编译器对inline的支持如何,需要参考相关文档,或者做些实验。而且,通常在debug状态下,inline是不做的,只有release编译,才会执行。
所有类型的函数都可以标记成inline,包括全局函数、成员函数、static函数。对于直接定义在class或struct中的成员函数,默认inline。如果定义在class/struct外的,则必须要通过inline关键字指定:
class A
{
void f1() {...} //inline
void f2();
inline void f3();
};
void A::f2() {...} //非inline
inline void f3() {...} //inline
最后,inline有一个有趣的现象。考虑如下函数:
int a[100];
inline void fill_a(int v) {
if(v==0)
return;
a[v]=v*10;
fill_a(v-1);
}
fill_a(9);//希望inline展开
尽管使用了inline关键字,但编译器是不会inline的。但是,inline还是可以做到的:
template <int n>
struct fill_a
{
void operator()() {
a[n]=n*10;
fill_a <n-1> ()(); //递归
}
}
template <>
struct fill_a <0>
{
void operator()() {
a[0]=0;
}
}
fill_a <9> ()();
此时,fill_a <9> ()();编译后(优化打开)的代码可能是这样的(伪码):
a[9]=90;
a[8]=80;
...
a[0]=0;
这样,便实现了递归的inline。
=================================
很抱歉啊,在没看到您的回复之后我就已经结贴了,新在重新拿出来。请教几个小问题。
上面的代码我还真看不懂啊。为什么操作符后面带两个()()?还有想要看懂这样的代码需要参考什么资料啊。
template <int n>
struct fill_a
{
void operator()() {
a[n]=n*10;
fill_a <n-1> ()(); //递归
}
}
这个我懂。
可是下面这个:
template <>
struct fill_a <0>
{
void operator()() {
a[0]=0;
}
}
就不懂了。它是函数还是类?
------解决方案--------------------
template <>
struct fill_a <0>
{
void operator()() {
a[0]=0;
}
}
=======================
这个是类.
void operator()()是对函数调用操作符 operator()的重载.一个类重载了operator()
后, 其对象就可以象函数那样调用了. STL中的防函数, boost中的function等等都用
到这个特性.
fill_a <0> filla;
filla(); // 调用operator(), 看起来与一个函数调用没有区别.
上面的operator()重裁不带参数, 返回null.
假如有另一个重载如int operator()(int a, int b), 你就可以传参数
和接收返回值了.
int result = filla(a, b)
.................
------解决方案--------------------
【Ref】
函数对象概述
关 键 词:对象
阅读提示:函数对象是比函数更加通用的概念,因为函数对象可以定义跨越多次调用的可持久的部分(类似静态局部变量),同时又能够从对象的外面进行初始化和检查(和静态局部变量不同)。
顾名思义,就是在某种方式上表现得象一个函数的对象。典型地,它是指一个类的实例,这个类定义了应用操作符operator()。
函数对象是比函数更加通用的概念,因为函数对象可以定义跨越多次调用的可持久的部分(类似静态局部变量),同时又能够从对象的外面进行初始化和检查(和静态局部变量不同)。例如: