关于inline函数的问题

时间:2021-06-25 18:50:29
我对于inline函数的理解是:它基本上是用来取代C中带参数的宏.
比如对于函数:
inline f(int a){return sizeof(a);}

调用f(5);/*只考虑实参为常量表达式的情况*/
在编译的时候将被展开为 sizeof(5)进而被编译器算出
结果是4

也就是说f(5)可以认为是一个常量表达式//对不对?我觉得是

可是对于:

int main(){
  enum{ A=f(5) };
}

为什么编译报错?//VC6和VS2005下都报错?
说f(5)的地方需要一个常量表达式.

这是怎么回是?编译器的问题吗?

21 个解决方案

#1


楼主在说啥?

int main(){
  enum{ A=f(5) };
}

这个跟inline有联系么?A是什么?

#2


inline函数在它被调用的地方被展开,省去了调用的堆栈开销。有可能在某些情况下,一些inline被优化成常量。

你这里enum跟inline没什么关系吧,enum定义类型,中不能调用函数吧。编译器无法给你替换。

#3


本帖最后由 Loaden 于 2010-05-01 10:08:40 编辑
与常量没有任何关系。
一些资料在介绍宏的危害时,可能会提到inline函数有 宏的效率,但两者不是一回事。
inline与否,取决于编译器。
用户的inline声明,只是向编译器提出的建议!

一般来讲,在类的定义体中写的成员函数,默认都会被编译器inline掉,甚至连inline的声明都不需要。
编译器的参数,可以控制inline的尺度:比如VC的/Ob0 /Ob1

#4


enum不能这么用吧...

#5


up Loaden~~
inline 只是对编译器提出要求,编译器会根据具体情况决定是否把函数代码嵌入到调用的地方
枚举中也不应该有函数~~

#6


书上说的是展开。。。

#7


引用 2 楼 cattycat 的回复:
有可能在某些情况下,一些inline被优化成常量。
你这里enum跟inline没什么关系吧,enum定义类型,中不能调用函数吧。编译器无法给你替换。

inline f(int a){return sizeof(a);}
f(5);
我觉得这里就是你所说的"某些情况下,一些inline被优化成常量。"

既然优化为常量了,f(5)就不算调用函数,而算常量表达式
从而enum{ A=f(5) };也就不算调用函数了是不是?

#8


引用 3 楼 loaden 的回复:
与常量没有任何关系。
一些资料在介绍宏的危害时,可能会提到inline函数有宏的效率,但两者不是一回事。
inline与否,取决于编译器。
用户的inline声明,只是向编译器提出的建议!

一般来讲,在类的定义体中写的成员函数,默认都会被编译器inline掉,甚至连inline的声明都不需要。
编译器的参数,可以控制inline的尺度:比如VC的/Ob0 /Ob1

我觉得
inline f(int a){return sizeof(a);}
这样的inline请求应该会被编译器接受,而且我用release模式编译的.

#9


引用 8 楼 yyg990441 的回复:
我觉得
inline f(int a){return sizeof(a);}
这样的inline请求应该会被编译器接受,而且我用release模式编译的.

语法和优化是两码事。

函数始终是函数,无论它有没有被内联(况且还是个“建议”内联)。
而函数调用表达式是不包括在常量表达式里面的。

#10


引用 5 楼 thefirstz 的回复:
up Loaden~~
inline 只是对编译器提出要求,编译器会根据具体情况决定是否把函数代码嵌入到调用的地方
枚举中也不应该有函数~~

你说的是,如果inline请求没有被编译器接受,那么我的枚举中才算有函数.但是如果inline请求被编译器接受了呢?是不是就不算在enum中调用函数?从而编译可以通过?

#11


引用 3 楼 loaden 的回复:
用户的inline声明,只是向编译器提出的建议!


说的很到位啊

#12


想楼上各位说的,你这里定义的enum、sizeof、inline没有任何关系。
inline函数不一定返回常量,所以在展开之前enum{A=f(5)}在语法上就无法通过编译,因为f是函数,返回值不确定。
但是这样当然是可以的enum{A=sizeof(int)},因为sizeof总是(被替换)为常量。

#13



我认为这里的问题不是会不会内联的问题,”内联是一种请求“,大部分人都知道。不管这里的inline会不会被内联,都不能通过编译,这是语法问题!
引用 11 楼 zhoutanliang 的回复:
引用 3 楼 loaden 的回复:

用户的inline声明,只是向编译器提出的建议!



说的很到位啊

#14


也就是说,inline首先就是一个函数,函数可以返回任何值,inline也可以返回任何值。inline的展开不是在预处理期(区别于宏),而是在编译器,语法分析之后。enum需要常量,但函数不保证返回常量(当然),所以语法分析就会产生错误。

#15


引用 14 楼 ivanff 的回复:
也就是说,inline首先就是一个函数,函数可以返回任何值,inline也可以返回任何值。inline的展开不是在预处理期(区别于宏),而是在编译器,语法分析之后。enum需要常量,但函数不保证返回常量(当然),所以语法分析就会产生错误。

inline展开确实在编译期,但是应该在编译期的第一步...所以还是在语法分析之前啊

#16


呃……

#17


inline不是在语法分析之前展开的,先语法分析,最后生成汇编的时候才给你展开的。

#18


引用 17 楼 cattycat 的回复:
inline不是在语法分析之前展开的,先语法分析,最后生成汇编的时候才给你展开的。

cattycat这么说有什么权威的根据吗?

#19


常量表达式不包含函数调用表达式,所以这个从语法上就是错的,无论编译器如何分析都不能违背这一点……

#20


我没看到权威的说法,但我根据编译原理课程中学到的,编译器的过程中推断的,你即使不是inline的,在enum中调用函数也不对吧。编译器首先扫描程序,生成各种符号表,在语法分析阶段看到enum里面的函数调用就不对了。有可能在生成符号表的时候就会认为enum中函数调用不对。
当然你可以看 提高c++性能中关于内联的介绍部分。

#21


希望楼主接受这种说法,如果你没学过编译原理,那就默默地接受。
这个问题到现在已经很清楚了。
引用 20 楼 cattycat 的回复:
我没看到权威的说法,但我根据编译原理课程中学到的,编译器的过程中推断的,你即使不是inline的,在enum中调用函数也不对吧。编译器首先扫描程序,生成各种符号表,在语法分析阶段看到enum里面的函数调用就不对了。有可能在生成符号表的时候就会认为enum中函数调用不对。
当然你可以看 提高c++性能中关于内联的介绍部分。

#1


楼主在说啥?

int main(){
  enum{ A=f(5) };
}

这个跟inline有联系么?A是什么?

#2


inline函数在它被调用的地方被展开,省去了调用的堆栈开销。有可能在某些情况下,一些inline被优化成常量。

你这里enum跟inline没什么关系吧,enum定义类型,中不能调用函数吧。编译器无法给你替换。

#3


本帖最后由 Loaden 于 2010-05-01 10:08:40 编辑
与常量没有任何关系。
一些资料在介绍宏的危害时,可能会提到inline函数有 宏的效率,但两者不是一回事。
inline与否,取决于编译器。
用户的inline声明,只是向编译器提出的建议!

一般来讲,在类的定义体中写的成员函数,默认都会被编译器inline掉,甚至连inline的声明都不需要。
编译器的参数,可以控制inline的尺度:比如VC的/Ob0 /Ob1

#4


enum不能这么用吧...

#5


up Loaden~~
inline 只是对编译器提出要求,编译器会根据具体情况决定是否把函数代码嵌入到调用的地方
枚举中也不应该有函数~~

#6


书上说的是展开。。。

#7


引用 2 楼 cattycat 的回复:
有可能在某些情况下,一些inline被优化成常量。
你这里enum跟inline没什么关系吧,enum定义类型,中不能调用函数吧。编译器无法给你替换。

inline f(int a){return sizeof(a);}
f(5);
我觉得这里就是你所说的"某些情况下,一些inline被优化成常量。"

既然优化为常量了,f(5)就不算调用函数,而算常量表达式
从而enum{ A=f(5) };也就不算调用函数了是不是?

#8


引用 3 楼 loaden 的回复:
与常量没有任何关系。
一些资料在介绍宏的危害时,可能会提到inline函数有宏的效率,但两者不是一回事。
inline与否,取决于编译器。
用户的inline声明,只是向编译器提出的建议!

一般来讲,在类的定义体中写的成员函数,默认都会被编译器inline掉,甚至连inline的声明都不需要。
编译器的参数,可以控制inline的尺度:比如VC的/Ob0 /Ob1

我觉得
inline f(int a){return sizeof(a);}
这样的inline请求应该会被编译器接受,而且我用release模式编译的.

#9


引用 8 楼 yyg990441 的回复:
我觉得
inline f(int a){return sizeof(a);}
这样的inline请求应该会被编译器接受,而且我用release模式编译的.

语法和优化是两码事。

函数始终是函数,无论它有没有被内联(况且还是个“建议”内联)。
而函数调用表达式是不包括在常量表达式里面的。

#10


引用 5 楼 thefirstz 的回复:
up Loaden~~
inline 只是对编译器提出要求,编译器会根据具体情况决定是否把函数代码嵌入到调用的地方
枚举中也不应该有函数~~

你说的是,如果inline请求没有被编译器接受,那么我的枚举中才算有函数.但是如果inline请求被编译器接受了呢?是不是就不算在enum中调用函数?从而编译可以通过?

#11


引用 3 楼 loaden 的回复:
用户的inline声明,只是向编译器提出的建议!


说的很到位啊

#12


想楼上各位说的,你这里定义的enum、sizeof、inline没有任何关系。
inline函数不一定返回常量,所以在展开之前enum{A=f(5)}在语法上就无法通过编译,因为f是函数,返回值不确定。
但是这样当然是可以的enum{A=sizeof(int)},因为sizeof总是(被替换)为常量。

#13



我认为这里的问题不是会不会内联的问题,”内联是一种请求“,大部分人都知道。不管这里的inline会不会被内联,都不能通过编译,这是语法问题!
引用 11 楼 zhoutanliang 的回复:
引用 3 楼 loaden 的回复:

用户的inline声明,只是向编译器提出的建议!



说的很到位啊

#14


也就是说,inline首先就是一个函数,函数可以返回任何值,inline也可以返回任何值。inline的展开不是在预处理期(区别于宏),而是在编译器,语法分析之后。enum需要常量,但函数不保证返回常量(当然),所以语法分析就会产生错误。

#15


引用 14 楼 ivanff 的回复:
也就是说,inline首先就是一个函数,函数可以返回任何值,inline也可以返回任何值。inline的展开不是在预处理期(区别于宏),而是在编译器,语法分析之后。enum需要常量,但函数不保证返回常量(当然),所以语法分析就会产生错误。

inline展开确实在编译期,但是应该在编译期的第一步...所以还是在语法分析之前啊

#16


呃……

#17


inline不是在语法分析之前展开的,先语法分析,最后生成汇编的时候才给你展开的。

#18


引用 17 楼 cattycat 的回复:
inline不是在语法分析之前展开的,先语法分析,最后生成汇编的时候才给你展开的。

cattycat这么说有什么权威的根据吗?

#19


常量表达式不包含函数调用表达式,所以这个从语法上就是错的,无论编译器如何分析都不能违背这一点……

#20


我没看到权威的说法,但我根据编译原理课程中学到的,编译器的过程中推断的,你即使不是inline的,在enum中调用函数也不对吧。编译器首先扫描程序,生成各种符号表,在语法分析阶段看到enum里面的函数调用就不对了。有可能在生成符号表的时候就会认为enum中函数调用不对。
当然你可以看 提高c++性能中关于内联的介绍部分。

#21


希望楼主接受这种说法,如果你没学过编译原理,那就默默地接受。
这个问题到现在已经很清楚了。
引用 20 楼 cattycat 的回复:
我没看到权威的说法,但我根据编译原理课程中学到的,编译器的过程中推断的,你即使不是inline的,在enum中调用函数也不对吧。编译器首先扫描程序,生成各种符号表,在语法分析阶段看到enum里面的函数调用就不对了。有可能在生成符号表的时候就会认为enum中函数调用不对。
当然你可以看 提高c++性能中关于内联的介绍部分。