Как этот код C ++ компилируется без оператора возврата конца? - PullRequest
2 голосов
/ 09 сентября 2009

Я наткнулся на следующий код, который прекрасно компилируется (с использованием Visual Studio 2005):

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

Почему это компилируется, если в конце метода нет оператора return?

Ответы [ 4 ]

20 голосов
/ 09 сентября 2009

Это для поддержки обратной совместимости с C, которая не требует строго возврата из всех функций. В этих случаях вам просто оставалось последнее значение в возвращаемой позиции (стек или регистр).

Если это компилируется без предупреждения, хотя у вас, вероятно, недостаточно высокий уровень ошибок. Большинство компиляторов предупреждают об этом сейчас.

5 голосов
/ 09 сентября 2009

Можно написать код, который гарантированно всегда будет возвращать значение, но компилятор может не понять это. Один тривиальный пример будет:

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

Что касается компилятора, вполне возможно, что все операторы 3 if оцениваются как false, и в этом случае управление падает с конца функции, возвращая неопределенный результат. Однако математически мы знаем, что это невозможно, поэтому эта функция определила поведение.

Да, умный компилятор мог бы понять это, но представьте, что при целочисленных сравнениях у нас были вызовы внешних функций, определенных в отдельной единице перевода. Затем, как люди, мы можем доказать, что все пути управления возвращают значения, но компилятор, конечно, не может этого понять.

Причина, по которой это разрешено, заключается в совместимости с C, а причина, по которой это допускает C, - совместимость с унаследованным кодом C, который был написан до стандартизации C (до ANSI). Был код, который делал именно это, поэтому, чтобы такой код оставался действительным и безошибочным, стандарт C допускал это. Однако позволить элементу управления покинуть функцию без возврата значения - все еще неопределенное поведение.

Любой достойный компилятор должен предоставить предупреждение об этом; в зависимости от вашего компилятора вам, возможно, придется повысить уровень предупреждения. Я считаю, что опция для этого предупреждения с gcc - -Wextra, которая также включает в себя кучу других предупреждений.

5 голосов
/ 09 сентября 2009

Установите уровень предупреждения на 4 и попробуйте. Не все пути управления возвращают значение, которое я помню, получая это предупреждение.

0 голосов
/ 09 сентября 2009

Возможно, ваш конкретный компилятор не так хорошо анализирует управление потоком, как следовало бы.

Какую версию компилятора вы используете и какие ключи используете для компиляции?

...