C ++自动关键字。为什么魔术呢?


144

从我用来学习C ++的所有材料中,auto一直以来都是一个奇怪的存储期限说明符,没有任何用处。但是就在最近,我遇到了将其本身用作类型名称的代码。出于好奇,我尝试了一下,它假定了我碰巧分配给它的任何类型!

突然地,STL迭代器以及所有使用模板的东西都易于编写10倍。感觉就像我在使用像Python这样的“有趣”语言。

这个关键词在我的一生中都在哪里?您会说这是Visual Studio专用的还是便携式的,从而破坏了我的梦想?


18
不是。魔法。这是新的(哦,是的,双关语是多么糟糕)。现在异步是未来(喘气
sehe 2011年

2
这是有关自动关键字的参考en.cppreference.com/w/cpp/language/auto
andyqee 2015年

Answers:


149

auto 是C ++从C那里“继承”的关键字,该关键字几乎永远存在,但实际上从未使用过,因为只有两个可能的条件:要么不允许,要么默认使用。

autoC ++ 11中,使用表示推断类型是新的。

同时,用与函数模板的模板类型推导相同的方法auto x = initializerx从类型推导类型initializer。考虑这样的函数模板:

template<class T>
int whatever(T t) { 
    // point A
};

在A点,T根据传递给参数的值将类型分配给whatever。当您这样做时auto x = initializer;,将使用相同的类型推导xinitializer用于初始化它的类型中确定其类型。

这意味着,编译器需要实现的大多数类型推导机制auto已经存在,并且可用于任何甚至尝试实现C ++ 98/03的编译器上的模板。这样,auto对于几乎所有编译器团队来说,添加支持显然都相当容易-添加非常迅速,而且似乎也没有与之相关的错误。

最初编写此答案时(2011年,在C ++ 11标准上墨未干之前)auto已经相当便于移植。如今,它已在所有主流编译器中完全移植。避免出现这种情况的唯一明显原因是,如果您需要编写与C编译器兼容的代码,或者您有针对性地针对某些您不知道支持它的利基编译器(例如,一些人仍在编写代码)使用Borland,Watcom等公司的编译器进行MS-DOS升级,这几十年来还没有看到重大的升级。如果您使用的是任何主流编译器的合理最新版本,则没有理由完全避免使用它。


23

它只是采用了通常无用的关键字,并为其提供了新的更好的功能。它是C ++ 11中的标准,大多数甚至支持C ++ 11的C ++编译器都将支持它。


哦! 啊哈,从没想过C ++语言是可以改变的东西。我将不得不查找他们在此C ++ 11中添加的其他内容,我听到了一些C ++ 0x,但从没有深入研究它。
安妮·奎因

7
@Clairvoire C ++ 0x是临时名称。它已于本月发布,因此成为C ++ 11。
R. Martinho Fernandes

13

对于变量,指定将从其初始值设定项自动推断出要声明的变量的类型。对于函数,指定返回类型为尾随返回类型,或者从其返回语句中推论得出(自C ++ 14起)。

句法

auto variable initializer   (1) (since C++11)

auto function -> return type    (2) (since C++11)

auto function   (3) (since C++14)

decltype(auto) variable initializer (4) (since C++14)

decltype(auto) function (5) (since C++14)

auto :: (6) (concepts TS)

cv(optional) auto ref(optional) parameter   (7) (since C++14)

说明

1)在块范围,名称空间范围,for循环的初始化语句等中声明变量时,关键字auto可用作类型说明符。确定了初始化程序的类型后,编译器将使用函数调用中模板参数推导的规则来确定将替换关键字auto的类型(有关详细信息,请参见模板参数推导#Other上下文)。关键字auto可能附带修饰符,例如const或&,它们将参与类型推导。例如,给定const auto& i = expr;template<class U> void f(const U& u)如果函数调用,则i的类型恰好是虚构模板中参数u的类型。f(expr)被编译。因此,根据初始化程序,可以将auto &&推导出为左值引用或右值引用,该值在基于范围的for循环中使用。如果使用auto声明多个变量,则推导的类型必须匹配。例如,声明格式错误auto i = 0, d = 0.0;,而声明auto i = 0, *p = &i;格式正确,而auto推导为int。

2)在使用尾随返回类型语法的函数声明中,关键字auto不执行自动类型检测。它仅用作语法的一部分。

3)在不使用尾随返回类型语法的函数声明中,关键字auto表示将使用模板参数推导规则从返回语句的操作数推导返回类型。

4)如果变量的声明类型为decltype(auto),则将关键字auto替换为其初始值设定项的表达式(或表达式列表),并使用decltype的规则推导实际类型。

5)如果将函数的返回类型声明为decltype(auto),则将关键字auto替换为其函数的return语句的操作数,并使用decltype的规则推导实际的返回类型。

6)形式为auto ::的嵌套名称说明符是一个占位符,它按照约束类型占位符推导的规则由类或枚举类型代替。

7)Lambda表达式中的参数声明。(自C ++ 14起)函数参数声明。(概念TS)

注意 在C ++ 11之前,auto具有存储持续时间说明符的语义。auto f() -> int, i = 0;不允许在一个声明中混合使用自动变量和函数,因为in 不允许。

有关更多信息:http : //en.cppreference.com/w/cpp/language/auto


11

此功能并非一生都存在。自2010年以来,Visual Studio已支持该功能。这是C ++ 11的新功能,因此它不是Visual Studio独有的,而且可以移植。大多数编译器已经支持它。


3

它无处不在……这是C ++ 11实现中的新标准C ++功能。话虽这么说,虽然它是简化对象声明以及清理某些调用范例的语法(即基于范围的for循环)的绝佳工具,但不要过度使用/滥用它:-)


3

auto关键字指定将要从其初始值设定项中自动推断出要声明的变量的类型。对于函数,如果它们的返回类型是auto,那么它将在运行时由返回类型expression求值。

当我们必须使用迭代器时,它可能非常有用。例如,对于下面的代码,我们可以简单地使用“ auto”而不是编写整个迭代器语法。

int main() 
{ 

// Initialize set 
set<int> s; 

s.insert(1); 
s.insert(4); 
s.insert(2); 
s.insert(5); 
s.insert(3); 

// iterator pointing to 
// position where 2 is 
auto pos = s.find(3); 

// prints the set elements 
cout << "The set elements after 3 are: "; 
for (auto it = pos; it != s.end(); it++) 
    cout << *it << " "; 

return 0; 
}

这就是我们可以使用“ auto”关键字的方式


0

神奇的是,它减少了为传递给特定函数的每个变量类型编写代码的能力。考虑一下C语言中与Python类似的print()函数。

#include <iostream>
#include <string>
#include <array>

using namespace std;

void print(auto arg) {
     cout<<arg<<" ";
}

int main()
{
  string f = "String";//tok assigned
  int x = 998;
  double a = 4.785;
  string b = "C++ Auto !";
//In an opt-code ASCII token stream would be iterated from tok's as:
  print(a);
  print(b);
  print(x);
  print(f);
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.