Возврат из функции 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, и человек, который обновил его, просто не думал очень ясно.