递归内联函数
我有这个文件:
//Q2a.h
#ifndef Q2A_H
#define Q2A_H
inline int MyFactorial(int a)
{
if (a < 2)
return 1;
return a*MyFactorial(a-1);
}
int NumPermutations(int b);
#endif
//Q2a.cpp
#include "Q2a.h"
int NumPermutations(int b)
{
return MyFactorial(b);
}
and file with the main- Q2b.cpp
我注意到,当存在递归函数时,编译器通常会忽略内联减速。 但我的问题是为什么如果我删除内联声明,我可以这样做:
g++ -Wall -g -c Q2a.cpp -o Q2a.o
g++ -Wall -g -c Q2b.cpp -o Q2b.o
这些都很好,但是在链接阶段:
g++ -Wall -g -c Q2a.o Q2b.o -o Q2
我收到错误:`MyFactorial(int) 的多重定义
i have this files:
//Q2a.h
#ifndef Q2A_H
#define Q2A_H
inline int MyFactorial(int a)
{
if (a < 2)
return 1;
return a*MyFactorial(a-1);
}
int NumPermutations(int b);
#endif
//Q2a.cpp
#include "Q2a.h"
int NumPermutations(int b)
{
return MyFactorial(b);
}
and file with the main- Q2b.cpp
i notice that the compiler usually ignore the inline decleration when there are recursive functions .
but my question is why if i remove the inline declaration, i can do:
g++ -Wall -g -c Q2a.cpp -o Q2a.o
g++ -Wall -g -c Q2b.cpp -o Q2b.o
those are fine, but in the linkage stage:
g++ -Wall -g -c Q2a.o Q2b.o -o Q2
i get an error: multiple definition of `MyFactorial(int)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
因为当您
#include "Q2a.h"
时,您实际上是在对内容进行文本替换,因此 Q2a.cpp 和 Q2b.cpp 最终都会定义一个名为MyFactorial( )
。您要么需要使用内联,要么在源文件之一中定义该函数。请注意,使用
inline
对递归函数没有多大帮助!Because when you
#include "Q2a.h"
, you're essentially doing a text substitution of the contents, so both Q2a.cpp and Q2b.cpp end up defining a function calledMyFactorial()
. You either need to useinline
, or define the function in one of the source files.Note that using
inline
won't help very much with a recursive function!使用 GCC 将函数声明为内联函数只会提示编译器内联该函数。但是,编译器仍然会生成一个非内联函数,您可以从不同的编译单元调用该函数。
在您的情况下,这些函数存在名称冲突。简单地说:内联并不意味着静态。
您想要做的是将函数声明为静态内联,
这将告诉编译器您希望函数内联,并且 - 如果编译器决定内联它 - 相同函数的静态版本不存在必需的。如果编译器无法内联该函数,它将确保该函数是静态的,例如,该函数的名称是 C 文件的本地名称,并且在程序链接期间不会发生名称冲突。
提示:
编译器有不同的行为。如果您将来想在不同平台上编译代码,请确保将定义隐藏在宏中。
例如,我必须对 GCC 和 Visual Studio 使用
static inline
,对 TI Code Composer DSP/嵌入式 ARM 编译器使用简单的_inline
。后来的编译器不理解普通内联,因为它是非标准的,也不会理解 static _inline 。With GCC declaring a function as
inline
will just hint the compiler to inline the function. However, the compiler will still generate a non-inline function that you can call from a different compilation unit.These functions had a name collision in your case. Simply said: inline doesn't imply static.
What you want to do is to declare the functions as
static inline
This will tell the compile that you want your function inline, and - if the compiler decides to inline it - no static version of the same function is required. It otoh the compiler can't inline the function it will make sure that the function is static, e.g. the name of the function is local to the C-file and no name collisions during linking of the program will occur.
Hint:
Compilers have different behaviour. If you want to compile the code on a different platform in the future make sure that you hide the definition in a macro.
For example I have to use
static inline
for the GCC and Visual Studio and a simple_inline
for the TI Code Composer DSP/embedded ARM compiler. The later compiler doesn't understand a plain inline because it is non-standard and won't understand static _inline either.当您声明函数
内联
时,您更改了适用于函数定义的规则。非内联函数只能在程序中定义一次;相反,内联函数可以在多个翻译单元中定义,尽管定义必须相同并且该函数必须在使用该函数的每个翻译中定义。
通过删除
内联
,您将删除之前的“一个定义规则”的豁免。When you declare a function
inline
you change the rules that apply for the definitions of your function.A non-
inline
function must only be defined once in a program; in contrast aninline
function may be defined in multiple translation units, although the definitions must be identical and the function must be defined in every translation in which it is used.By removing
inline
, you are removing the exemption from the "one definition rule" that you had previously.