Вопрос

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

void Foo()
{
  // ...
}

void Bar()
{
  return Foo();
}

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

void Foo()
{
  // ...
}

void Bar()
{
  Foo();

  // no more expressions -- i.e., implicit return here
}
Это было полезно?

Решение

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

Другие советы

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

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

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

В этом случае бар действителен для void, но также действителен, должен изменять тип возврата. Тем не менее, если он просто называется F, то этот код сломался бы, если бы не пустота. Используя возврат f (); Синтаксис гарантирует сохранение возвращаемого значения FOO (), если он существует, и обеспечивает пустоту ().

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

Шаблоны:

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(); утверждения в коммутаторе и хотели сделать его более компактным.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top