Возврат из функции Void в C++
рассмотрим следующий фрагмент:
void Foo()
{
// ...
}
void Bar()
{
return Foo();
}
какова законная причина использовать вышеизложенное в C++ в отличие от более распространенного подхода:
void Foo()
{
// ...
}
void Bar()
{
Foo();
// no more expressions -- i.e., implicit return here
}
7 ответов
вероятно, нет пользы в вашем примере, но есть некоторые ситуации, когда трудно иметь дело с void
в коде шаблона, и я ожидаю, что это правило помогает иногда. Очень надуманный пример:
#include <iostream>
template <typename T>
T retval() {
return T();
}
template <>
void retval() {
return;
}
template <>
int retval() {
return 23;
}
template <typename T>
T do_something() {
std::cout << "doing something\n";
}
template <typename T>
T do_something_and_return() {
do_something<T>();
return retval<T>();
}
int main() {
std::cout << do_something_and_return<int>() << "\n";
std::cout << do_something_and_return<void*>() << "\n";
do_something_and_return<void>();
}
обратите внимание, что только main
приходится справляться с тем, что в void
case нет ничего, чтобы вернуться из retval
. Промежуточная функция do_something_and_return
универсален.
конечно, это только получает вас до сих пор - если do_something_and_return
wanted, в обычном случае, в магазине retval
в переменной и сделать что - то с ним, прежде чем вернуться, то вы все равно будете в беде-вам придется специализироваться (или перегрузка) do_something_and_return
для void.
Это довольно бесполезная конструкция, которая не служит никакой цели, если он используется с шаблонами. То есть, если вы определили функции шаблона, которые возвращают значение, которое может быть "void".
вы бы использовали его в общем коде, где возвращаемое значение Foo () неизвестно или может быть изменено. Подумайте:
template<typename Foo, typename T> T Bar(Foo f) {
return f();
}
в этом случае Bar действителен для void, но также действителен при изменении типа возврата. Однако, если он просто вызвал f, то этот код сломается, если T не будет пустым. Использование return f(); синтаксис гарантирует сохранение возвращаемого значения Foo (), если оно существует, и допускает void ().
кроме того, явное возвращение-хорошая привычка попасть.
Шаблоны:
template <typename T, typename R>
R some_kind_of_wrapper(R (*func)(T), T t)
{
/* Do something interesting to t */
return func(t);
}
int func1(int i) { /* ... */ return i; }
void func2(const std::string& str) { /* ... */ }
int main()
{
int i = some_kind_of_wrapper(&func1, 42);
some_kind_of_wrapper(&func2, "Hello, World!");
return 0;
}
не будучи в состоянии вернуть пустоту,return func(t)
в шаблоне не будет работать, когда его попросили обернуть func2
.
единственная причина я могу думать, если у вас был длинный список return Foo();
операторы в коммутаторе и хотели сделать его более компактным.
причина-возвращение памяти, как математика.ч всегда возвращается. математика.h не имеет пустоты и пустых аргументов. Есть много практических ситуаций, когда вам нужна память.
может быть случай, когда Foo()
первоначально вернуло значение, но позже было изменено на void
, и человек, который обновил его, просто не думал очень ясно.