Функции, для возвращаемого значения которых указан тип void
, вторую форму оператора return
могут использовать только для возвращения результата вызова другой функции, которая возвращает тип void
. Возвращение любого другого выражения из функции типа void
приведет к ошибке при компиляции.
Вторая форма оператора return
предназначена для возвращения результата из функции. Каждый случай возвращения значения типа, отличного от void
,
Хотя язык С++ не может гарантировать правильность результата, он способен гарантировать, что каждое возвращаемое функцией значение будет соответствовать объявленному типу. Это может получиться не во всех случаях, компилятор попытается обеспечить возвращение значения и выход только через допустимый оператор return
. Например:
//
bool str_subrange(const string &str1, const string &str2) {
//
if (str1.size() == str2.size())
return str1 == str2; //
//
auto size = (str1.size() < str2.size())
? str1.size() : str2.size();
//
for (decltype(size) i = 0; i != size; ++i) {
if (str1[i] != str2[i])
return; //
//
}
//
//
//
}
Оператор return
в цикле for
является ошибочным потому, что он не в состоянии вернуть значение. Эту ошибку компилятор должен обнаружить.
Вторая ошибка заключается в том, что функция не имеет оператора return после цикла. Если произойдет вызов этой функции со строкой, являющейся подмножеством другой, процесс выполнения минует цикл for
. Однако оператор return
для этого случая не предусмотрен. Эту ошибку компилятор может и не обнаружить. В этом случае поведение программы во время выполнения будет непредсказуемо.
return
после цикла, который этот оператор содержит, является особенно коварной ошибкой. Однако большинство компиляторов ее не обнаружит.
Значения функций возвращаются тем же способом, каким инициализируются переменные и параметры: возвращаемое значение используется для инициализации временного объекта в точке вызова, и этот временный объект является результатом вызова функции.
В функциях, возвращающих локальные переменные, важно иметь в виду правила инициализации. Например, можно написать функцию, которой передают счетчик, слово и окончание. Функция возвращает множественную форму слова, если счетчик больше 1:
//
string make_plural(size_t ctr, const string &word,
const string &ending) {
return (ctr > 1) ? word + ending : word;
}
Тип возвращаемого значения этой функции — string
, это значит, что возвращаемое значение копируется в точке вызова. Функция возвращает копию значения word
или безымянную временную строку, полученную конкатенацией word
и ending
.
Когда функция возвращает ссылку, она, подобно любой другой ссылке, является только другим именем для объекта, на который ссылается. Рассмотрим, например, функцию, возвращающую ссылку на более короткую из двух переданный ей строк:
// возвратить ссылку на строку, которая короче
const string &shorterString(const string &s1, const string &s2) {
return s1.size() <= s2.size() ? s1 : s2;
}
Параметры и возвращаемое значение имеют тип ссылки на const string
. Строки не копируются ни при вызове функции, ни при возвращении результата.