考虑以下代码片段:
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
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;
}
如果无法返回 void,当要求换行
return func(t)
时,模板中的 func2
将无法工作。
我能想到的唯一原因是,如果您在 switch 中有一长串
return Foo();
语句,并且希望使其更加紧凑。
原因是返回内存,就像 math.h 总是返回一样。 math.h 没有 void 也没有空参数。有很多实际情况需要记忆。
可能是
Foo()
本来返回了一个值,后来改成了void
,只是更新的人想的不太清楚。