函数声明中使用 -> 的含义

6

可能是重复问题:
函数声明后面的“->”是什么意思?

我刚刚遇到了以下使用新auto关键字的C++函数示例,希望有人能帮助我理解这个语法的含义。

template <class T, class U>
auto add(T t, U u) -> decltype(t + u);

auto f = [](int a, int b) -> int {
   return a*b;
};

具体来说,我对函数签名中的->的使用感到困惑,我希望这些可以按以下方式编写

template <class T, class U>
auto add(T t, U u)
{
    decltype(t + u);
}

auto f = [](int a, int b){
    return a*b;
};

-> 运算符是做什么的,我在哪里可以学习更多关于这种语法的知识?

6个回答

13

这里的->运算符是做什么用的?

这是一个尾置返回类型。与其写成:

int f();

您可以等效地编写:

auto f() -> int;

如果返回类型取决于函数参数类型,则需要使用此形式;直到它们被声明之后,参数才可用:
decltype(t+u) add(T t, U u); // Error: uses `t` and `u` before they're declared
auto add(T t, U u) -> decltype(t + u); // OK

此外,如果您想指定lambda的返回类型,则必须使用这种形式;尽管如您所指出的,在许多情况下(包括此案例)您根本不需要指定它。

3
[dcl.spec.auto]/2解释了如何使用auto返回类型编写函数声明:

在任何允许此类声明符的上下文中,auto类型说明符都可以与带有尾随返回类型(8.3.5)的函数声明符一起出现。

然后,在[dcl.fct]/12中,有一个注释:

当函数的返回类型比较复杂时,typedef和尾随返回类型有时很方便。例如,函数fpif可以这样声明:

typedef int IFUNC(int);
IFUNC* fpif(int);

或者

auto fpif(int)->int(*)(int)

一个尾随返回类型最适用于那些在声明符之前指定会更加复杂的类型。
template <class T, class U> auto add(T t, U u) -> decltype(t + u);

相比之下
template <class T, class U> decltype((*(T*)0) + (*(U*)0)) add(T t, U u);

2

这种语法(被称为尾置返回类型)是使用表达式作为返回类型的一种解决方法,如下所示:

template <class T, class U>
   decltype(t + u) add(T t, U u) { ... }

在C++中,这种写法是不正确的。

必须说明的是,这个问题在维基百科已经被解释得足够清楚了(我想)。


1
这不正确,因为它在tu可用之前就使用了它们(它们只在参数列表中声明)。 - R. Martinho Fernandes

1

-> 是一个 尾返回类型

C++11 提出了一种替代函数声明语法。 auto 关键字取代了通常的函数返回类型,实际的返回类型放在 -> 后面。

例如,

auto f (int a, int b) -> int;

等同于

int f(int a, int b);

这个功能在模板函数中非常有用,因为返回类型必须从模板参数中推断出来。

例如,

template <class T, class U>
auto add(T t, U u) -> decltype(t + u);

返回类型将是表达式 (t+u) 的类型。


1
“->”运算符在其中的作用是什么?我在哪里可以了解更多关于这个语法的知识? cprogramming上有一个非常好的解释。
使用“->”(在您的情况下)或auto,decltype的本质是为了方便,让您更专注于编程逻辑。
“trailing return type”(->)帮助您在函数声明中包含返回��型信息。
至于您的备选示例:
auto add(T t, U u)
{
    decltype(t + u);
}

如果函数相当复杂,那么对于程序读者来说,弄清预期的返回类型将会相当困难(不是显而易见的)。

0

在函数声明中,->运算符指定了返回类型为"auto"的函数的返回类型。它在C++11标准的第8章中定义。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接