Возврат из функции Void в C ++ - PullRequest
       12

Возврат из функции Void в C ++

11 голосов
/ 08 августа 2010

Рассмотрим следующий фрагмент:

void Foo()
{
  // ...
}

void Bar()
{
  return Foo();
}

Какая законная причина использовать вышеизложенное в C ++, в отличие от более распространенного подхода:

void Foo()
{
  // ...
}

void Bar()
{
  Foo();

  // no more expressions -- i.e., implicit return here
}

Ответы [ 7 ]

16 голосов
/ 08 августа 2010

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

Конечно, это только покажется вам - если бы do_something_and_return хотел, в обычном случае, сохранить retval в переменной и что-то с ней сделать перед возвратом, тогда у вас все еще будут проблемы - вам придется специализироваться (или перегружаться) do_something_and_return для void.

9 голосов
/ 08 августа 2010

Это довольно бесполезная конструкция, которая не имеет смысла, если она не используется с шаблонами.То есть, если вы определили шаблонные функции, которые возвращают значение, которое может быть 'void'.

7 голосов
/ 08 августа 2010

Вы бы использовали его в общем коде, где возвращаемое значение Foo () неизвестно или может быть изменено.Обратите внимание:

template<typename Foo, typename T> T Bar(Foo f) {
    return f();
}

В этом случае Bar действителен для void, но также действителен при изменении типа возвращаемого значения.Однако если бы он просто вызвал f, то этот код сломался бы, если бы T был не пустым.Используя return f ();синтаксис гарантирует сохранение возвращаемого значения Foo (), если оно существует, и AND допускает void ().

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

4 голосов
/ 08 августа 2010

Шаблоны:

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;
}

Без возможности возврата void return func(t) в шаблоне не будет работать, когда его попросят обернуть func2.

0 голосов
/ 08 августа 2010

Может случиться так, что Foo() первоначально вернул значение, но позже было изменено на void, а тот, кто его обновил, просто не очень ясно думал.

0 голосов
/ 08 августа 2010

Причина в возврате памяти, как всегда возвращается math.h.math.h не имеет пустоты и пустых аргументов.Есть много практических ситуаций, когда вам нужна память.

0 голосов
/ 08 августа 2010

Единственная причина, по которой я могу придумать, состоит в том, что у вас был длинный список return Foo(); операторов в коммутаторе и вы хотели сделать его более компактным.

...