内联函数与宏的区别(C++)
展开全部
(1)什么是内联函数?
内联函数是指那些定义在类体内的成员函数,即该函数的函数体放在类体内。
(2)为什么要引入内联函数?
当然,引入内联函数的主要目的是:解决程序中函数调用的效率问题。另外,前面我们讲到了宏,里面有这么一个例子:
#define ABS(x) ((x)>0? (x):-(x))
当++i出现时,宏就会歪曲我们的意思,换句话说就是:宏的定义很容易产生二意性。
我们可以看到宏有一些难以避免的问题,怎么解决呢?前面我们已经尽力替换了。
下面我们用内联函数来解决这些问题。
(3)为什么inline能取代宏?
1、 inline 定义的类的内联函数,函数的代码被放入符号表中,在使用时直接进行替换,(像宏一样展开),没有了调用的开销,效率也很高。
2、很明显,类的内联函数也是一个真正的函数,编译器在调用一个内联函数时,会首先检查它的参数的类型,保证调用正确。然后进行一系列的相关检查,就像对待任何一个真正的函数一样。这样就消除了它的隐患和局限性。
3、 inline 可以作为某个类的成员函数,当然就可以在其中使用所在类的保护成员及私有成员。
(4)内联函数和宏的区别?
内联函数和宏的区别在于,宏是由预处理器对宏进行替代,而内联函数是通过编译器控制来实现的。而且内联函数是真正的函数,只是在需要用到的时候,内联函数像宏一样的展开,所以取消了函数的参数压栈,减少了调用的开销。你可以象调用函数一样来调用内联函数,而不必担心会产生于处理宏的一些问题。内联函数与带参数的宏定义进行下比较,它们的代码效率是一样,但是内联欢函数要优于宏定义,因为内联函数遵循的类型和作用域规则,它与一般函数更相近,在一些编译器中,一旦关上内联扩展,将与一般函数一样进行调用,比较方便。
(5)什么时候用内联函数?
内联函数在C++类中,应用最广的,应该是用来定义存取函数。我们定义的类中一般会把数据成员定义成私有的或者保护的,这样,外界就不能直接读写我们类成员的数据了。对于私有或者保护成员的读写就必须使用成员接口函数来进行。如果我们把这些读写成
员函数定义成内联函数的话,将会获得比较好的效率。
Class A
{
Private:
int nTest;
Public:
int readtest() { return nTest;}
void settest(int I) { nTest=I; }
}
(6)如何使用内联函数?
我们可以用inline来定义内联函数。
inline int A (int x) { return 2*x; }
不过,任何在类的说明部分定义的函数都会被自动的认为是内联函数。
(7)内联函数的优缺点?
我们可以把它作为一般的函数一样调用,但是由于内联函数在需要的时候,会像宏一样展开,所以执行速度确比一般函数的执行速度要快。当然,内联函数也有一定的局限性。就是函数中的执行代码不能太多了,如果,内联函数的函数体过大,一般的编译器会放弃内联方式,而采用普通的方式调用函数。(换句话说就是,你使用内联函数,只不过是向编译器提出一个申请,编译器可以拒绝你的申请)这样,内联函数就和普通函数执行效率一样了。
(8)如何禁止函数进行内联?
如果使用VC++,可以使用/Ob命令行参数。当然,也可以在程序中使用 #pragma auto_inline达到相同的目的。
(9)注意事项:
1.在内联函数内不允许用循环语句和开关语句。
2.内联函数的定义必须出现在内联函数第一次被调用之前。
内联函数是指那些定义在类体内的成员函数,即该函数的函数体放在类体内。
(2)为什么要引入内联函数?
当然,引入内联函数的主要目的是:解决程序中函数调用的效率问题。另外,前面我们讲到了宏,里面有这么一个例子:
#define ABS(x) ((x)>0? (x):-(x))
当++i出现时,宏就会歪曲我们的意思,换句话说就是:宏的定义很容易产生二意性。
我们可以看到宏有一些难以避免的问题,怎么解决呢?前面我们已经尽力替换了。
下面我们用内联函数来解决这些问题。
(3)为什么inline能取代宏?
1、 inline 定义的类的内联函数,函数的代码被放入符号表中,在使用时直接进行替换,(像宏一样展开),没有了调用的开销,效率也很高。
2、很明显,类的内联函数也是一个真正的函数,编译器在调用一个内联函数时,会首先检查它的参数的类型,保证调用正确。然后进行一系列的相关检查,就像对待任何一个真正的函数一样。这样就消除了它的隐患和局限性。
3、 inline 可以作为某个类的成员函数,当然就可以在其中使用所在类的保护成员及私有成员。
(4)内联函数和宏的区别?
内联函数和宏的区别在于,宏是由预处理器对宏进行替代,而内联函数是通过编译器控制来实现的。而且内联函数是真正的函数,只是在需要用到的时候,内联函数像宏一样的展开,所以取消了函数的参数压栈,减少了调用的开销。你可以象调用函数一样来调用内联函数,而不必担心会产生于处理宏的一些问题。内联函数与带参数的宏定义进行下比较,它们的代码效率是一样,但是内联欢函数要优于宏定义,因为内联函数遵循的类型和作用域规则,它与一般函数更相近,在一些编译器中,一旦关上内联扩展,将与一般函数一样进行调用,比较方便。
(5)什么时候用内联函数?
内联函数在C++类中,应用最广的,应该是用来定义存取函数。我们定义的类中一般会把数据成员定义成私有的或者保护的,这样,外界就不能直接读写我们类成员的数据了。对于私有或者保护成员的读写就必须使用成员接口函数来进行。如果我们把这些读写成
员函数定义成内联函数的话,将会获得比较好的效率。
Class A
{
Private:
int nTest;
Public:
int readtest() { return nTest;}
void settest(int I) { nTest=I; }
}
(6)如何使用内联函数?
我们可以用inline来定义内联函数。
inline int A (int x) { return 2*x; }
不过,任何在类的说明部分定义的函数都会被自动的认为是内联函数。
(7)内联函数的优缺点?
我们可以把它作为一般的函数一样调用,但是由于内联函数在需要的时候,会像宏一样展开,所以执行速度确比一般函数的执行速度要快。当然,内联函数也有一定的局限性。就是函数中的执行代码不能太多了,如果,内联函数的函数体过大,一般的编译器会放弃内联方式,而采用普通的方式调用函数。(换句话说就是,你使用内联函数,只不过是向编译器提出一个申请,编译器可以拒绝你的申请)这样,内联函数就和普通函数执行效率一样了。
(8)如何禁止函数进行内联?
如果使用VC++,可以使用/Ob命令行参数。当然,也可以在程序中使用 #pragma auto_inline达到相同的目的。
(9)注意事项:
1.在内联函数内不允许用循环语句和开关语句。
2.内联函数的定义必须出现在内联函数第一次被调用之前。
展开全部
宏是一种“代替”关系,内联是给编译器的一种提示,例如
#define PI 3.14
这条宏真的执行起来的时候,差不多就相当于文本编辑器的“查找与替换”,只是编译器在预编译的时候把能查找到的PI直接替换成3.14而已。(当然也是有区别的,例如一个变量叫aPI就不会背替换,字符串中出现的PI也不会被替换)。我的意思主要是,你要理解这个是替换而已,所以宏定义才经常出现括号,就是怕替换会出错,例如
#define A 2+3
如果我们用int c = 4 * A;
就会被替换为int c = 4 * 2 + 3;
这样的结果显然不一定是我们看到的,所以改为
#define A (2+3)
后,就被替换为
int c = 4 * (2+3);
这个结果可能更符合我们的要求。
总而言之,所谓的宏,只是一种出现在预编译阶段的替换而已
内联函数是给编译器的一种提示。如果可以内联,那么就相当于编译器会把内联函数里的内容“复制”到函数调用的地方,例如一个函数
inline int fun(int a)
{
return a+2;
}
调用时
int c = fun(2);
这样内联之后我们可以理解为变换为
int c = 2+2;
这样的做法主要是为了避免函数调用的开销,因为对汇编级来说,函数调用要保存现场,要用call指令,之后还要ret,这是有开销的,尤其是在这样的函数很多次调用时。所以一个如果不算长的函数能避免这些开销,那么显然可以提高程序效率。
不过只能说inline是对编译器的一种提示,并不是你写上inline编译器就一定会给你内联的,最后是否能内联还要看编译器判断你的函数是否符合内联的条件,是否内联能有效率提高而已。所以说最后是否内联主要看编译器的意见,这个关键字只是给编译器一个提示。实际上在某些编译器的某些优化设置下,是视所有函数为内联函数的。内联也不一定完全就是优点,在部分时候也可能会加大程序编译后的体积的。无论如何,这些判断都是编译器去做的。
#define PI 3.14
这条宏真的执行起来的时候,差不多就相当于文本编辑器的“查找与替换”,只是编译器在预编译的时候把能查找到的PI直接替换成3.14而已。(当然也是有区别的,例如一个变量叫aPI就不会背替换,字符串中出现的PI也不会被替换)。我的意思主要是,你要理解这个是替换而已,所以宏定义才经常出现括号,就是怕替换会出错,例如
#define A 2+3
如果我们用int c = 4 * A;
就会被替换为int c = 4 * 2 + 3;
这样的结果显然不一定是我们看到的,所以改为
#define A (2+3)
后,就被替换为
int c = 4 * (2+3);
这个结果可能更符合我们的要求。
总而言之,所谓的宏,只是一种出现在预编译阶段的替换而已
内联函数是给编译器的一种提示。如果可以内联,那么就相当于编译器会把内联函数里的内容“复制”到函数调用的地方,例如一个函数
inline int fun(int a)
{
return a+2;
}
调用时
int c = fun(2);
这样内联之后我们可以理解为变换为
int c = 2+2;
这样的做法主要是为了避免函数调用的开销,因为对汇编级来说,函数调用要保存现场,要用call指令,之后还要ret,这是有开销的,尤其是在这样的函数很多次调用时。所以一个如果不算长的函数能避免这些开销,那么显然可以提高程序效率。
不过只能说inline是对编译器的一种提示,并不是你写上inline编译器就一定会给你内联的,最后是否能内联还要看编译器判断你的函数是否符合内联的条件,是否内联能有效率提高而已。所以说最后是否内联主要看编译器的意见,这个关键字只是给编译器一个提示。实际上在某些编译器的某些优化设置下,是视所有函数为内联函数的。内联也不一定完全就是优点,在部分时候也可能会加大程序编译后的体积的。无论如何,这些判断都是编译器去做的。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
C++中的内联函数提供了宏之上的功能。宏是内联代码的简单实现形式。。不过两者有很大的区别。
内联函数采用的是值传递,而宏定义采用的是对等替换。这一点非常重要,宏定义没用好,很可能在使用过程中陷入误区。
例如下面这个宏:
#define MAX(a, b) a>b?a:b
当我们这样使用宏时,没有什么问题: MAX( num1, num2 ); 因为宏展开后变成 num1>num2?num1:num2;。 但是,如果是这样调用的,MAX( 17+32, 25+21); 呢,编译时出现错误,原因是,宏展开后变成:17+32>25+21?17+32:25+21,Woh,这是什么啊?
所以,宏在使用时,参数一定要加上括号,上述的那个例子改成如下所示就能解决问题了。
#define MAX( (a), (b) ) (a)>(b)?(a)b)
即使是这样,也不这个宏也还是有Bug,因为如果我这样调用 MAX(i++,j++); , 经过这个宏以后,i和j都被累加了两次,这绝不是我们想要的。所以,在宏的使用上还是要谨慎考虑,因为宏展开是的结果是很难让人预料的。而且虽然,宏的执行很快(因为没有函数调用的开销),但宏会让源代码澎涨,使目标文件尺寸变大,(如:一个50行的宏,程序中有1000个地方用到,宏展开后会很不得了),相反不能让程序执行得更快(因为执行文件变大,运行时系统换页频繁)。因此,在决定是用函数,还是用宏时得要小心。
相同点:两者都是在预处理阶段,对代码块,进行替换。。
内联函数采用的是值传递,而宏定义采用的是对等替换。这一点非常重要,宏定义没用好,很可能在使用过程中陷入误区。
例如下面这个宏:
#define MAX(a, b) a>b?a:b
当我们这样使用宏时,没有什么问题: MAX( num1, num2 ); 因为宏展开后变成 num1>num2?num1:num2;。 但是,如果是这样调用的,MAX( 17+32, 25+21); 呢,编译时出现错误,原因是,宏展开后变成:17+32>25+21?17+32:25+21,Woh,这是什么啊?
所以,宏在使用时,参数一定要加上括号,上述的那个例子改成如下所示就能解决问题了。
#define MAX( (a), (b) ) (a)>(b)?(a)b)
即使是这样,也不这个宏也还是有Bug,因为如果我这样调用 MAX(i++,j++); , 经过这个宏以后,i和j都被累加了两次,这绝不是我们想要的。所以,在宏的使用上还是要谨慎考虑,因为宏展开是的结果是很难让人预料的。而且虽然,宏的执行很快(因为没有函数调用的开销),但宏会让源代码澎涨,使目标文件尺寸变大,(如:一个50行的宏,程序中有1000个地方用到,宏展开后会很不得了),相反不能让程序执行得更快(因为执行文件变大,运行时系统换页频繁)。因此,在决定是用函数,还是用宏时得要小心。
相同点:两者都是在预处理阶段,对代码块,进行替换。。
参考资料: C++ primer Plus
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询