考虑以下代码片段:
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
在一个变量中并在返回之前对其进行操作,那么你仍然会遇到麻烦——你必须为void
专门化(或重载)do_something_and_return
。这是一个毫无用处的结构,除非它与模板一起使用。也就是说,如果您已经定义了返回值可能为 "void" 的模板函数。
当你的代码是通用的,而且Foo()函数的返回值未知或可能会改变时,你可以使用它。例如:
template<typename Foo, typename T> T Bar(Foo f) {
return f();
}
模板:
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
,并且更新它的人没有思考得很清楚。