1

Possible Duplicate:
Two questions about inline functions in C++

Hi, Can i declare my function as "inline" if it is a recursive function? I've heard it may be a bit problematic/dangerous. I'd like to understand the reasons behind all this.

Thanks!

Community
  • 1
  • 1
limlim
  • 357
  • 2
  • 5
  • 10

2 Answers2

3

You can declare it inline if you like, but it will do nothing because the function obviously cannot be inlined. Note that, in general, the compiler is free to completely ignore any and all inline requests.

That being said, it may actually get inlined if the compiler removes the recursion. A common technique used is the tail-call optimisation, which changes functions that call themselves recursively at the end of the function into iterative functions. For example:

int factorial(int n)
{
  if (n == 1) return 1;
  return n * factorial(n - 1);
}

would get transformed into:

int factorial(int n, int accum = 1)
{
start:
  if (n == 1) return accum;
  accum *= n;
  n = n - 1;
  goto start;
}

which could be inlined.

Note that while the compiler is free to not inline functions declared with inline, it cannot ignore your request for internal linkage i.e. you can still define your inline recursive function in a header file and include it with many cpp files without worrying about multiple definitions.

Community
  • 1
  • 1
Peter Alexander
  • 53,344
  • 14
  • 119
  • 168
  • 3
    `inline` does not do nothing. It changes the "one definition" rules so that the function can be defined in multiple translation units. The compiler cannot ignore this aspect of `inline` whether or not it actually can or does perform inline expansion of function calls. – CB Bailey Oct 02 '10 at 22:25
  • Ok, ok, Mr. Pedantic. Obviously I was referring to the fact that it won't actually inline the function, but I'll add that for completeness :) – Peter Alexander Oct 02 '10 at 22:29
  • c++ doesn't support tail recursion. – JoshD Oct 02 '10 at 22:30
  • 1
    I honestly don't think I'm being _too_ pedantic on this one. So many people misunderstand what `inline` hints and what it actually requires that it never hurts to be explicit and complete. ... IMHO – CB Bailey Oct 02 '10 at 22:31
  • 2
    @JohnD: C++ doesn't prohibit tail recursion. So long as the effect of what the compiler does not deviate from what the standard requires, a compiler can perform what transformations and optimizations it deems fit. – CB Bailey Oct 02 '10 at 22:33
  • @Charles: I see. I've been lied to!!! Are there any compilers that do this optimization that you're aware of? – JoshD Oct 02 '10 at 22:42
  • @JoshD: There's a question for that: http://stackoverflow.com/questions/34125/which-if-any-c-compilers-do-tail-recursion-optimization – Ben Voigt Oct 02 '10 at 22:45
  • 1
    gcc happily compiles this into a iterative solution at levels greater than `-O1`. `unsigned sum(unsigned x) { return x ? x + sum(x - 1) : 0; }` – CB Bailey Oct 02 '10 at 22:50
  • `inline` functions have external linkage unless they're otherwise given internal linkage (e.g. by a previous declaration as a `static` function). `inline` doesn't give a function automatic internal linkage. – CB Bailey Oct 03 '10 at 00:07
  • Members of the `goto`-less cult are now on your *tail*, *calling* and chanting your name for your premature *optimizations*, and casting a spell upon thee. – Mateen Ulhaq Apr 09 '11 at 23:31
0

To understand the reasons why inlining doesn't make sense, you have to think about what inlining a function does.

When it's inline, it will essentially ask the compiler to replace the function call with the body of the function (the compiler can ignore this). So if you did this recursively, it'd be infinite. Let's look at an example:

int factorial(int n) {
  if (n == 0 || n == 1)
    return 1;
  return n * factorial(n-1);
}

Now, if this were inlined, we'd first replace a call to factorial with it's body. Looking at the body of factorial itself, we'd have to replace the call factorial(n-1). This gives:

int factorial(int n) {
  if (n == 0 || n == 1)
    return 1;
  return n * ((( if (n-1 == 0 || n-1 == 1)
    return 1;
  return (n-1) * factorial(n-1-1); )));
}

I'm using tripple parenthesis to indicate code replacement. Of course this isn't exactly valid code, but it ilustrates my point.

From here, we have another factorial call inside the new code, so we replace that, and on ad infinitum.

So, that's reasoning behind why such a thing isn't done. Modern compilers are clever enough not to do this for exactly this reason, though.

JoshD
  • 12,490
  • 3
  • 42
  • 53
  • 1
    It would be a poor compiler that went into an infinite loop because of a legal use of `inline`. `inline` never requires inline expansion of function calls and clearly a compiler should attempt it if it's going to cause a compilation failure. – CB Bailey Oct 02 '10 at 22:28
  • this will not cause the compiler to be in an infinite loop. compiler will just ignore it. – Donotalo Oct 02 '10 at 22:30
  • Yes. I noted that the compiler can choose not to inline. I'm trying to explain why a recursive function wouldn't be inlined as the question asked (if I understood the question.) – JoshD Oct 02 '10 at 22:32
  • typo: obviously I meant: "...should **not** attempt..." – CB Bailey Oct 02 '10 at 22:34
  • @JoshD, that's not what you've written though - "You'll cause an infinite loop in the compiler" - that seems to very definitively say that declaring a recursive function `inline` will cause an infinite loop, which, if true in your case, means you need to switch to another compiler! – Praetorian Oct 02 '10 at 22:35
  • @Praetorian: I see that would be misleading (I meant it hypothetically along with the hypothetical example, but I see that it isn't clear the way I wrote it). I've changed it. Thanks for pointing it out. – JoshD Oct 02 '10 at 22:40