Инструкция return почему возвращает 0 от чего зависит возвращаемое значение

If, in your code, you say that your function returns a value, but you don’t actually return one:

int my_function(int x)
{
    // bad practice!
}

… that is an error bad practice. You said that you were going to return a value (in this case, an ‘int’) but you did not.

Similarly, if there are multiple paths through your function:

int my_function(int x)
{
    if (x == 3)
        return 42;  // good

    // bad!
}

and you’ve again declared the intent to return a value, but some paths through your function do not, that is also an error bad practice; you have broken your promise to the callers of your function.

All paths through a function should end up at a return statement:

int my_function(int x)
{
    if (x == 3)
        return 42;  // good

    return 1;  // good
}

If you don’t want to return any values, then declare the function void:

void my_function(int x)
{
    // good
}

UPDATE: above, you may notice that I replaced «an error» with «bad practice». That’s because the word ‘error’ means something very particular within the C standard, and forgetting a return statement doesn’t meet that definition (instead, it’s considered to be «undefined behavior,» and your compiler might not even complain.) However, you as a human being should consider it an error in your code, and avoid forgetting return statements on all exit paths out of your functions.

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

Далее предстоит разобраться с принципами работы функции return в C++. Эта информация пригодится преимущественно начинающим разработчикам.

Описание функции возврата

Все пользовательские функции после завершения выполнения инструкций способны возвращать значения туда, откуда они были вызваны. Пример – int main. Она в конце работы всегда возвращает значение в операционную систему. Связано это с тем, что ОС изначально вызывала main для работы программного обеспечения.

В C++ и C имеются операторы возврата. Они называются функциями перехода. Используются для возврата значений или остановки выполнения операции. Называется оператор перехода return (ретурном).

При обработке return происходит следующее:

  1. Выполнение имеющейся функции прекращается.
  2. Управление переходит обратно в точку вызова обработанной операции.
  3. Инструкции, написанные после return, никогда не выполняются.
  4. Если внутри функции отсутствует соответствующий оператор, при достижении закрывающейся фигурной скобки управление передается в точку вызова обработанной операции. Возвращаемое значение не определяется.

Операторы return имеются несколько сценариев использования. Всего их два. Далее они будут рассмотрены более подробно.

Использование внутри основной функции

Это – первый метод применения returning. Он делает следующее:

  1. Return останавливает исполнение программы. Происходит присваивание значения 0 (zero) или 1 (one). Они указываются на статус выполнения.
  2. Соответствующие коды использовались в C в виде соглашения. Связано это с отсутствием поддержки объектов, классов и исключений непосредственно в языке.
  3. Return 0 возвращает функции 0. Данная запись указывает на успешное выполнение заданных операций. Функция обработана так, как было задумано изначально.
  4. Return 1 возвращает 1. Указывает на наличие ошибки или сбоя при выполнении приложения. Данная запись свидетельствует о том, что функция не работает по задуманному предназначению.

Что делает returned 0, понятно. Стоит обратить внимание на то, что операционные системы могут самостоятельно завершать приложения с определенными кодами статуса выхода. Это возможно тогда, когда выполняется некоторый спектр недопустимых операций. А еще в зависимости от операционной системы на устройстве пользователя могут меняться соглашения о кодах возврата. Это достаточно редкая ситуация.

Внутри пользовательских функций

Второй вариант использования returns в программном коде – это внутри пользовательских функций. В C++ данный подход широко используется на практике. Соответствующий язык программирования рассматривает логическое значение в качестве отдельного типа данных с двумя «исходами» — истина (true) и ложь (false).

Значения 0 и 1 являются целочисленными (тип int). Они не могут быть неявно преобразованы в логические. Это приводит к тому, что:

  • return 0 делает возврат false из заданной инструкции;
  • return 1 возвращает истину.

Необходимо помнить, что не всегда returns применяются с 0 и 1. Далее предстоит рассмотреть наглядный пример с отличающимся возвращаемым параметром.

Принцип работы – пример

Чтобы лучше разбираться в операторах перехода в C++, рекомендуется рассмотреть принцип их работы на наглядном примере. Необходимо написать приложение, которое будет запрашивать у клиента число, а затем выводить его квадрат. Для уточнения «цифры» используется отдельная инструкция. Ее предстоит создать самостоятельно.

Делается это так:

  1. Сначала требуется создать функцию, которая запрашивает число на вывод с консоли:.
  2. Во второй строке создается функция типа int под названием EnterNumer.
  3. Строки 3-6 используются для описания инструкций, выполняемых после вызова функции. Сначала клиенту на экране предлагается ввод целого числа. Далее программа создает переменную для него и получит заданный параметр.
  4. Описанная функция вызывается из главной (main): .
  5. Функция, запрашивающая и получающая число, вызвана. По завершению работы она должна вернуть в main число, которое было указано пользователем. Эта операция прописана в 7 строке кода. После его обработки произойдет возврат переменной int. Поэтому инструкция выглядит как return input: .
  6. Чтобы сохранить значения, необходимо воспользоваться переменной. Она инициализируется функцией EnterNumber(). Это происходит в строке 11: .
  7. Соответствующая инструкция указывает на то, что в памяти резервируется место для переменной с именем num типа int. Далее происходит инициализация ее значением, возвращенным из функции EnterNumber. Предварительно запускается выполнение предусматриваемых инструкций.
  8. Необходимо завершить приложение выводом на дисплей квадрата числа, полученного из функции EnterNumber(). Для этого используется std::cout:.

При обработке соответствующего кода на экране появится такой результат:

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

Тип void

Тип функции void в C++ — это ничего или пустота. Он указывает компилятору на то, что соответствующая команда не возвращает никаких параметров. Если в ее конце устанавливается оператор return, программа просто не пройдет стадию компиляции.

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

Написанное приложение печатает две строчки текста, хранимых в двух «алгоритмах» типа void. Они ничего не вернут – только выполняют заданные инструкции. После этого происходит после обращения к ним main().

Как быстрее разобраться с темой

Операторы перехода в C++ – это не так трудно, как кажется. Чтобы надписи типа return, include, main и другие не вызывали вопросов, рекомендуется пройти дистанционные компьютерные курсы. На них с нуля пользователей научат разрабатывать приложения на разных языках – от Python до C++.

Пример – от образовательного центра OTUS. Пользователя в срок до 12 месяцев научат основам разработки. Люди смогут освоить любую IT-профессию. В процессе обучения гарантируется постоянное кураторство, много практики, а также интересные домашние задания. Ученику помогут составить портфолио. В конце курса выдается электронный сертификат, который подтверждает приобретенный спектр навыков и знаний.

Хотите освоить современную IT-специальность? Огромный выбор курсов по востребованным IT-направлениям есть в Otus! Ниже – один из них:

Завершает текущую функцию и возвращает указанное значение (если оно есть)вызывающей стороне.

Syntax

attr(optional)returnexpression(optional); (1)
attr(optional)returnbraced-init-list; (2) (since C++11)
attr(optional)co_returnexpression(optional); (3) (since C++20)
attr(optional)co_returnbraced-init-list; (4) (since C++20)
attr (начиная с C++11) последовательность любого количества атрибутов
expression выражение , конвертируемое в тип возвращаемого значения функции
braced-init-list закрытый список инициализаторов и другие списки скреплённых фигурными скобками

Explanation

1) Оценивает выражение, завершает текущую функцию и возвращает результат выражения вызывающей стороне после неявного преобразования в возвращаемый тип функции. Выражение является необязательным в функциях, чей тип возврата (возможно, cv-квалифицированный) void , и запрещен в конструкторах и в деструкторах.

3,4) В сопрограмме ключевое слово co_return должно использоваться вместо return для конечной точки приостановки ( подробности см. В сопрограммах ).

Notes

Если управление достигает конца.

  • функция с возвращаемым типом (возможно, cv-qualified) void ,
  • a constructor,
  • деструктор,или
  • function — try-block для функции с возвращаемым типом (возможно, cv-qualified) void

не сталкиваясь с оператором возврата, return; выполняется.

Если управление достигает конца основной функции , return 0; выполнен.

Выход из конца функции, возвращающей значение (кроме main ) без оператора return, является неопределенным поведением.

В функции, возвращающей (возможно, cv-qualified) void , можно использовать оператор return с выражением, если тип выражения (возможно, cv-qualified) void .

Если тип возвращаемого значения функции указан как тип заполнителя , он будет выведен из возвращаемого значения.

Инициализация копии результата вызова функции выполняется до уничтожения всех временных объектов в конце выражения, что, в свою очередь, являетсяsequenced-beforeуничтожение локальных переменных блока,содержащего оператор возврата.

(since C++14)

Возврат по значению может включать в себя создание и копирование / перемещение временного объекта, если только не используется разрешение копирования . В частности, условия копирования / перемещения следующие:

Автоматический переход от локальных переменных и параметров

Выражениеmove-eligibleЕсли это (возможно, в скобках) id-выражение , которое называет переменную, тип которой.

  • тип энергонезависимого объекта
  • или энергонезависимая ссылка rvalue на тип объекта
(since C++20)

и эта переменная объявляется.

  • в теле или
  • как параметр
самая внутренняя вложенная функция или лямбда-выражение.

Если выражение подходит для перемещения, выполняется разрешение перегрузки для выбора конструктора, который будет использоваться для инициализации возвращаемого значения, или, для co_return , для выбора перегрузки promise.return_value() (начиная с C++20) .twice:

  • сначала, как если бы выражение было выражением rvalue (таким образом, оно может выбрать конструктор перемещения ), и
    • если первое разрешение перегрузки не удалось или
  • это удалось, но конструктор перемещения не был выбран (формально первый параметр выбранного конструктора не был ссылкой rvalue на (возможно, cv-квалифицированный) тип выражения)
(until C++20)
  • затем разрешение перегрузки выполняется, как обычно, с выражением, рассматриваемым как lvalue (поэтому он может выбрать конструктор копирования ).
(until C++23)

Если выражение подходит для перемещения, оно обрабатывается как xvalue (таким образом, разрешение перегрузки может выбрать конструктор перемещения ).

(since C++23)
(since C++11)

Гарантированное устранение копий

Если выражение является значением, результирующий объект инициализируется непосредственно этим выражением. Это не включает конструктор копирования или перемещения, когда типы совпадают (см. Раздел «Разрешение копирования» ).

(since C++17)

Keywords

return, co_return.

Example

#include <iostream>
#include <string>
#include <utility>
 
void fa(int i)
{
    if (i == 2)
        return;
    std::cout << i << '\n';
} 
 
int fb(int i)
{
    if (i > 4)
        return 4;
    std::cout << i << '\n';
    return 2;
}
 
std::pair<std::string, int> fc(const char* p, int x)
{
    return {p, x};
}
 
void fd()
{
    return fa(10); 
}
 
int main()
{
    fa(2); 
    fa(1); 
 
    int i = fb(5); 
    i = fb(i);     
    std::cout << i << '\n'
              << fc("Hello", 7).second << '\n';
 
    fd();
}

Output:

Defect reports

Следующие отчеты о дефектах,изменяющих поведение,были применены ретроактивно к ранее опубликованным стандартам C++.

DR Applied to Поведение в опубликованном виде Correct behavior
CWG 1541 C++98 выражение не может быть опущено, если тип возвращаемого значения имеет значение cv-qualified void его можно опустить
CWG 1579 C++11 возврат путем переоборудования передвижного конструктора не разрешался converting move
включен поиск конструктора
CWG 1885 C++14 последовательность уничтожения автоматических переменных не была явной добавленные правила последовательности

See also

  • copy elision


C++

  • reinterpret_cast conversion

    Преобразование между типами путем переинтерпретации битового паттерна,лежащего в основе.

  • Требует выражения (начиная с C++20)

    Выдает выражение prvalue типа bool,описывающее ограничения.

  • Правило трех/пяти/ноля

    Если класс требует определяемого пользователем деструктора,конструктора копирования,оператора присваивания,то почти наверняка все три.

  • Scope

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

Как понять что надо ставить в выражении return? Когда ставить return 0 и все return c другими выражениями? как определить что надо возвращать ? я имею ввиду как определить что ставить после return(? )?
я просто не понимаю, что надо возвращать, я не понимаю что писать после return в скобках return(?)?
вот например :

int find_substr(char *s1, char *s2)
{
  register int t;
  char *p, *p2;

  for(t=0; s1[t]; t++) {
    p = &s1[t];
    p2 = s2;

    while(*p2 && *p2==*p) {
      p++;
      p2++;
    }
    if(!*p2) return t; /* 1-й оператор return */
  }
   return -1; /* 2-й оператор return */
}

почему там return -1, что это -1 обозначает , почему там стоит именно -1, а не 0 или не p?
как вообще понять в каких обстоятельствах и что ставить после return?

MSDN.WhiteKnight's user avatar

задан 16 июн 2014 в 13:31

1

Ваш вопрос по сути не имеет смысла. Он слишком общий что ли, сродни вопросу «когда нужно употреблять букву А«. Ответ на вопрос «что надо ставить в выражении return» в каждом конкретном случае зависит от логики функции, поэтому не существует какого-то универсального рецепта, который бы говорил, что «вот здесь пиши return 0, а тут return «Hello world».
Что касается приведенного примера — постарайтесь понять, что (а главное как) делает эта функция, тогда, вероятно, вы увидите логику в том, почему эта функция возвращает те или иные значения. В частности, -1 в функциях поиска обычно подразумевает, что искомое значение не было найдено. Однако, еще раз повторю — это лишь конкретный пример одной функции. Ответ на ваш вопрос должен вытекать из логики реализуемой функции в каждом конкретном случае

Nicolas Chabanovsky's user avatar

ответ дан 16 июн 2014 в 13:46

DreamChild's user avatar

DreamChildDreamChild

36.1k2 золотых знака44 серебряных знака85 бронзовых знаков

Данная функция, судя по всему, ищет подстроку в строке.

В случае успеха она возвращает t — позицию найденной подстроки (порядковый номер первого символа подстроки в данной строке).

В случае провала возвращает -1, т.к. это не является валидным порядковым номером символа в строке (нет символа с номером -1) и тот, кто вызвал эту функцию поймет, что подстрока не найдена.

Вообще возврат -1 — довольно распространенная практика в функциях, возвращающих позицию какого-либо объекта в упорядоченном списке.

ответ дан 16 июн 2014 в 13:36

Nofate's user avatar

NofateNofate

34.4k15 золотых знаков65 серебряных знаков94 бронзовых знака

int find_substr(char *s1, char *s2)

в описании функции первым идет тип переменной что она должна вернуть после выполнения.

Тебе решать нужно что-то от функции получить или нет.

Скажем,

int iResult=find_substr("строка 1","стр");
if (iResult==-1) //поиск окончился неудачей
...
;
else //поиск успешен!
...
;

В операнд return добавляешь нужные тебе значения (0,-1,-2, что угодно типа int), а потом анализируешь результат в iResult.

Если не нужно чего-то ждать от функции, то вместо int указываешь тип void.

Nicolas Chabanovsky's user avatar

ответ дан 16 июн 2014 в 13:47

Rapax's user avatar

RapaxRapax

4192 серебряных знака7 бронзовых знаков

What up, программач.
Т.е, указано, что return — это самый подходящий способ остановить программу.
Вот если указано return 0; — то программа закончиться.Я правильно понимаю?
А если ничего не указать?Она будет в памяти висеть или что?
А если указать 1?
Т.е. если указываешь 0, то это типа false.Можно значит false писать, кому что удобно?
Все никак не могу с этим ретурном разобраться.


  • Вопрос задан

  • 32811 просмотров

Вот если указано return 0; — то программа закончиться.Я правильно понимаю?

Только если это return в main().

return это команда закончить текущую функцию (и вернуть значение вызыающей функции)

А если ничего не указать?Она будет в памяти висеть или что?

С 1998 года она выполнит return 0 (опять же, справедливо только для main() ) как только достигнет конца функции main().

Т.е. если указываешь 0, то это типа false.

Это EXIT_SUCCESS.

А если указать 1?

Implementation defined. Обычно работает так же как и EXIT_FAILURE.

Фактически это код выхода. Он возвращается в ОС. Если программа была запущена из командной строки этот код выхода можно проверить чтобы узнать как была завершена программа.

Пригласить эксперта

main() — это входящая функция. И все же это именно функция, со всеми вытекающими свойствами.
Ее можно обьявить как void, а значит она не должна что либо возвращать и return писать не надо.
Все же многие не понимают по началу, что return, это не только остановка программы, но еще и вывод результата работы функций.
Пример:

//создаем свою собственную функцию, которая что-то делает и что-то возвращает.
int myrandom() {
    int a;
    a = rand()%100; //генерация случайного числа
    return a; // возвращаем результат генерации
}

//а вот наша программка, в которой мы вызовем эту функцию.
void main() {
  int s = myrandom(); // функция myrandom возвращает результат в переменную s.
  cout << s;
}


  • Показать ещё
    Загружается…

20 сент. 2023, в 03:07

500 руб./за проект

20 сент. 2023, в 02:34

40000 руб./за проект

20 сент. 2023, в 00:43

300 руб./в час

Минуточку внимания

Понравилась статья? Поделить с друзьями:
  • Инструкция reoflex акриловый грунт реофлекс 4 1 по применению
  • Инструкция sea doo gtx 300
  • Инструкция remote dog training collar инструкция на русском
  • Инструкция ipega pg 9076 на русском
  • Инструкция sdd jlr на русском