函数签名差异C ++

时间:2017-02-28 15:39:36

标签: c++11

你能解释一下这三个功能签名之间的区别吗?为什么auto可以用作返回的数据类型而不是参数声明?

//auto f1(auto x) { return x; }   not accepted

auto f1(int x) { return x; }

auto f2(double x) -> decltype(x) { return x; }

template <typename T> 
T f3(T x) { return x; }

3 个答案:

答案 0 :(得分:0)

  • f1获取int并返回int。 (auto在此处推断为int,因为返回表达式x的类型为int。)
  • f2需要double并返回double。 (这使用尾随返回类型,其中decltype(x)的评估结果为double,因为x的类型为double。)
  • f3是一个模板,将使用分配给T的给定参数类型进行实例化,因此它返回相同的类型。 (函数体必须使用给定类型T进行编译才能实例化该函数。)
  

为什么自动可以用作返回的数据类型而不是参数声明?

因为这是语言的定义方式。 auto也不是数据类型,它是推断类型的占位符。

答案 1 :(得分:0)

auto并不真正作为类型存在,在编译期间会被特定类型替换。因此,只有在编译器可以确定要使用的单个特定类型来代替auto关键字时,才能使用它。它不能用作泛型的形式来生成函数的多个变体。

  • auto f1(auto x) { return x; } // not accepted

在这种情况下,auto是什么类型的?它可能是任何东西。编译器无法决定将哪个类型放在那里以完成f1的签名。不允许编译器制作模板等多种变体。

  • auto f1(int x) { return x; }

auto可以推导为int,一切都很好。

  • auto f2(double x) -> decltype(x) { return x; }

auto可以推导为double,一切都很好。

  • template <typename T> T f3(T x) { return x; }

f3是模板化的,因此在您使用它之前它并不存在。当您使用它时,编译器将创建一个变体,其中T是您当前使用的类型。

答案 2 :(得分:0)

C ++ 11中auto说明符的主要任务是推导 编译时的给定值的类型。

auto A = 12;        // A deduced type is int
auto B = 4.3;       // B deduced type is double
auto C = "hello";   // C deduced type is const char*

这些都是可以使用auto的有效案例,因为它可以很容易地找出给定值的类型。

这样的事情是非法的:

auto D;

因为没有给定值

有了功能,没有任何改变。

void foo(auto var) { }   

当编译器生成你的函数 foo 时,它完全不知道用 auto 代替什么类型。

相反,其他三个函数都是有效的,因为编译器能够识别类型。

  

你能解释一下这三个功能签名之间的区别吗?

<强> 1

auto f1(int x) { return x; }

f1 的返回类型与返回值的类型相同 x

<强> 2

auto f2(double x) -> decltype(x) { return x; }

f2 的返回类型取决于参数 x 的类型,因为我们使用的是所谓的 trailing return type < / p>

当返回必须从表达式

推导出的类型时,它特别有用
template<typename T, typename U>
auto foo(T a, U b) -> decltype(a+b) { ... }

此处返回类型将是参数 a b

之间的总和所生成的类型
int a = 10 
double b = 2.3 
return type = int + double = double

char a = 'y';
char b = 'o';
return type = char + char = int

第3

template <typename T> 
T f3(T x) { return x; }

这里T只评估一种类型,参数和返回类型也是一样。

f3("hello");

此处 T 评估为 const char * ,因此参数 x 和返回类型将自动为const char *