2010-07-06 3 views
7

Хорошо, немного странности, которую я обнаружил с моим компилятором на C++.Поддерживает ли C++ операторы возврата?

У меня был не слишком сложный бит кода для рефакторинга, и мне случайно удавалось оставить путь, у которого не было оператора возврата. Виноват. С другой стороны, это скомпилировано и прервано, когда я запустил его, и этот путь был поражен, очевидно.

Вот мой вопрос: Является ли это ошибкой компилятора, или нет гарантии, что компилятор C++ обеспечит необходимость использования оператора return в функции возврата не-void?

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

+0

Какой компилятор вы используете? – Dennis

+3

Если на gcc используйте ['-Wreturn-type'] (http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html), возможно с' -Werror = '. –

+0

То же самое случилось со мной с gcc 4.4 –

ответ

11

Лично я думаю, что это должно быть ошибка:

int f() { 
} 

int main() { 
    int n = f(); 
    return 0; 
} 

но большинство компиляторов рассматривать это как предупреждение, и вы можете даже использовать переключатели компилятора, чтобы получить это предупреждение.Например, на г ++ вам нужно -Wall получить:

[[email protected] NeilB]$ g++ -Wall nr.cpp 
nr.cpp: In function 'int f()': 
nr.cpp:2: warning: no return statement in function returning non-void 

Конечно, с г ++ вы всегда должны составить по крайней мере -Wall в любом случае.

13

Нет гарантии, что компилятор C++ обеспечит это. Функция C++ могла выпрыгнуть из потока управления механизмами, неизвестными компилятору. Примером этого являются коммутаторы контекста, когда C++ используется для записи ядра ОС. Неоткрытое исключение, вызванное вызываемой функцией (код которой необязательно доступен для вызывающего), является другим.

Некоторые другие языки, такие как Java, явно применяют это со знанием, доступным во время компиляции, все пути возвращают значение. В C++ это неверно, как и во многих других случаях на языке, например, при доступе к массиву из его границ.

+0

«Функция C++ могла выпрыгнуть из потока управления механизмами, неизвестными компилятору». - Да, но поток будет возвращен обратно. В конце концов, переключатель контекста. Я действительно не вижу, что это связано с возвращаемыми значениями. Единственный случай, когда функция не будет возвращена, - это если выбрано исключение. – 2010-07-06 14:34:40

+0

@Neil не нужно. Например, вызов 'exit' не будет возвращаться назад. –

+1

@Johannes OK и abort() и завершение(). Но компилятор не может видеть, что это отрицает необходимость возврата, если только оно не рассматривает их как «специальные» в некотором роде. – 2010-07-06 14:39:14

4

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

В Visual Studio это предупреждение. И мы должны обратить внимание на все предупреждения ... правильно? :)

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

enum TriBool { Yes, No, Maybe }; 

TriBool GetResult(int input) { 
    if (TestOne(input)) { 
     return Yes; 
    } else if (TestTwo(input)) { 
     return No; 
    } 
} 

Принесите меня, потому что это старый код. Изначально там было «другое возвращение». :) Если TestOne и TestTwo находятся в другом компиляционном блоке, тогда, когда компилятор попадает в этот код, он не может сказать, могут ли TestOne и TestTwo возвращать false для данного ввода. Вы, как программист, который написал TestOne и TestTwo, знаете, что если TestOne не удастся, TestTwo преуспеет. Возможно, есть побочные эффекты этих тестов, поэтому они должны быть сделаны. Было бы лучше написать его без «else if»? Может быть. Вероятно. Но дело в том, что это законный C++, и компилятор не может знать, можно ли выйти без оператора return. Это, я согласен, уродливое и плохое кодирование, но это законно, и Visual Studio даст вам предупреждение, но оно будет компилироваться.

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

+0

Это не имеет никакого смысла. Компилятор musty знает, какие пути возможны для компиляции кода. – 2010-07-06 14:30:46

+1

@Neil Я думаю, что у него есть точка. Компилятор не всегда знает в момент компиляции *. Как будто у вас не было ни малейшего понятия, когда вы отправили свой комментарий, чтобы я опубликовал ответ на него. Но теперь вы знаете и, возможно, имеете предосторожности, чтобы ответить в свою очередь, или нет. Или вы полностью удивлены, как C++ будет, и делаете неопределенные вещи :) –

+1

Это ерунда ИМХО. График потока управления любой данной функции отлично известен компилятору после анализа его кода. Возможно, некоторые грани никогда не пересекаются при выполнении кода (думают о утверждениях), но компилятор рассматривает его как таковой, и все, что он вызывает, - это просто (слишком консервативное предположение). – jpalecek

Смежные вопросы