尾部返回类型在C++中是一个很奇怪的内容,我们应该只在必要的时候使用。我们要决定采用它作为一种通用风格的时候一定要小心,并尽量的保持这种风格。
首先看下列代码:
auto getMulticastHops() const -> int;
这是一种声明C++11语言中函数的方法。->int
部分称为尾部返回类型,这行代码和一下代码是相同的:
int getMulticastHops() const;
为什么要有尾部返回类型
有很好的理由在C++11中引入尾部返回类型。标准示例是函数模板,当其中返回类型取决于参数类型的时候。我们举个例子来看,一个函数有两个值相乘:
template<class T,class U>
auto multiply(T const& lhs,U const& rhs)->decltype(lhs* rhs)
{
return lhs * rhs;
}
我们可以使用std::declval
来避免使用尾部返回类型,只是这样的话代码就会肉眼可见的混乱不堪,很难快速阅读:
template<class T, class U>
decltype(std::declval<T>() * std::declval<U>())
multiply(T const& lhs, U const& rhs)
{
return lhs * rhs;
}
除此之外还有个例子是lambda表达式,其中语法不允许声明返回类型常规的方式。
什么是返回类型推导(return type deduction)
C++11的lamdba表达式已经对比较简单的情况进行了返回类型推导。C++14为更为一般的情况和普通函数添加了返回类型推导。上面的函数可以简单的写成:
template<class T, class U>
auto multiply(T const& lhs, U const& rhs)
{
return lhs * rhs;
}
返回类型推导可以帮助我们处理许多以前需要尾部返回类型的情况,当然不是所有的情况。例如,编译器总是根据值来推导返回值,而不是根据引用。因此如果我们想从一个lambda表达通过引用返回,就没有办法使用尾部返回类型。其他不能返回类型推导的情况还有没有主体函数的声明,当然这不会是lambda表达式。
不是什么时候都要使用尾部返回类型
现在在任何地方都使用尾部返回类型可能很有吸引力。有些人还认为它们使我们的代码更一致。有些人使用它们是因为它们必须在某些地方使用,但许多人也会使用它们,因为它们是新的,新的很酷。我们有很多这样的新特性和可能性。它们被大肆宣传,有时被过度使用。但是要记住我们使用一定要有正确的理由。现在也有一些反对这种风格的理由: