views:

282

answers:

4

I came across the following code that compiles fine (using Visual Studio 2005):

SomeObject SomeClass::getSomeThing()
{
    for each (SomeObject something in someMemberCollection)
    {
        if ( something.data == 0 )
        {
            return something;
        }
    }
    // No return statement here
}

Why does this compile if there is no return statement at the end of the method?

+20  A: 

This is to support backwards compatibility with C which did not strictly require a return from all functions. In those cases you were simply left with whatever the last value in the return position (stack or register).

If this is compiling without warning though you likely don't have your error level set high enough. Most compilers will warn about this now.

JaredPar
+5  A: 

Set the warning level to 4 and tryout.Not all control path returns a value is the warning I remember getting this warning.

yesraaj
A: 

Probably your particular compiler is not doing as good flow control analysis as it should.

What compiler version are you using and what switches are you using to compile with?

mcjabberz
+5  A: 

It's possible to write code that is guaranteed to always return a value, but the compiler might not be able to figure that out. One trivial example would be:

int func(int x)
{
    if(x > 0)
        return 1;
    else if(x == 0)
        return 0;
    else if(x < 0)
        return -1;
}

As far as the compiler is concerned, it's possible that all 3 if statements evaluate to false, in which case control would fall off the end of the function, returning an undefined result. Mathematically, though, we know it's impossible for that to happen, so this function has defined behavior.

Yes, a smarter compiler might be able to figure this out, but imagine that of integer comparisons, we had calls to external functions defined in a separate translation unit. Then, as humans we can prove that all control paths return values, but the compiler certainly can't figure that out.

The reason this is allowed is for compatibility with C, and the reason that C allows it is for compatibility with legacy C code that was written before C was standardized (pre-ANSI). There was code that did exactly this, so to allow such code to remain valid and error-free, the C standard permitted this. Letting control fall off a function without returning a value is still undefined behavior, though.

Any decent compiler should provide a warning about this; depending on your compiler, you may have to turn your warning level way up. I believe the option for this warning with gcc is -Wextra, which also includes a bunch of other warnings.

Adam Rosenfield