C ++自动关键字。为什么它很神奇?

时间:2011-09-28 00:01:06

标签: c++ types c++11 auto

从我以前学习C ++的所有材料来看,auto一直是一个奇怪的存储持续时间说明符,不能用于任何目的。但就在最近,我遇到的代码将其用作类型名称。出于好奇,我尝试了它,它假设我碰巧分配给它的类型!

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

这个关键词一直是我的一生?你会说它是视觉工作室独有的还是不可移植的?

8 个答案:

答案 0 :(得分:118)

auto是一个C ++“从C继承”的关键词,几乎永远存在于C中,但实际上从未使用过,因为只有两种可能的条件:要么是不允许的,要么是假设的默认值。

使用auto表示推导类型是C ++ 11的新功能。

与此同时,auto x = initializer从类型f x推导出initializer的类型,与模板类型推导适用于函数模板的方式相同。考虑一下这样的函数模板:

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

在A点,根据为T传递的参数值,已将类型分配给whatever。执行auto x = initializer;时,会使用相同的类型推导来确定用于初始化x的{​​{1}}类型的initializer类型。

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

当这个答案最初编写时(2011年,在C ++ 11标准的墨水干燥之前)auto已经非常便携了。如今,它在所有主流编译器中都是完全可移植的。避免它的唯一明显理由是,如果您需要编写与C编译器兼容的代码,或者您需要针对某些您不知道不支持它的利基编译器(例如,少数人仍然编写代码)对于使用Borland,Watcom等编译器的MS-DOS,几十年来没有出现过显着的升级)。如果您正在使用任何主流编译器的合理当前版本,那么根本没有理由避免它。

答案 1 :(得分:19)

它只是采用一个通常无用的关键字,并赋予它一个新的,更好的功能。它是C ++ 11中的标准,大多数C ++编译器甚至支持一些C ++ 11都支持它。

答案 2 :(得分:10)

这个功能一直没有出现过。自2010版以来,Visual Studio一直支持它。这是一个新的C ++ 11功能,因此它不是Visual Studio独有的,并且/将是可移植的。大多数编译器已经支持它了。

答案 3 :(得分:8)

对于变量,指定将从其初始化程序自动推导出正在声明的变量的类型。对于函数,指定返回类型是尾随返回类型,或者将从其返回语句中推断出来(自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 contexts)。关键字auto可以伴随有修饰符,例如const或&amp;,它们将参与类型推导。例如,给定const auto& i = expr;,如果编译函数调用template<class U> void f(const U& u),则i的类型正是假想模板f(expr)中参数u的类型。因此,汽车&amp;&amp;可以根据初始化器推导出左值引用或右值引用,初始化器用于基于范围的for循环。  如果auto用于声明多个变量,则推导出的类型必须匹配。例如,声明auto i = 0, d = 0.0;格式不正确,而声明auto i = 0, *p = &i;格式正确,自动推断为int。

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

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

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;中所示。

了解更多信息:http://en.cppreference.com/w/cpp/language/auto

答案 4 :(得分:4)

auto 关键字是 C++ 中一个重要且经常使用的关键字。初始化变量时,auto 关键字用于类型推断(也称为类型推导)。

关于 auto 关键字有 3 种不同的规则。

第一条规则

auto x = expr; ----> 没有指针或引用,只有变量名。在这种情况下,常量和引用将被忽略。

int  y = 10;
int& r = y;
auto x = r; // The type of variable x is int. (Reference Ignored)

const int y = 10;
auto x = y; // The type of variable x is int. (Const Ignored)

int y = 10;
const int& r = y;
auto x = r; // The type of variable x is int. (Both const and reference Ignored)

const int a[10] = {};
auto x = a; //  x is const int *. (Array to pointer conversion)

Note : When the name defined by auto is given a value with the name of a function,
       the type inference will be done as a function pointer.

第二条规则

auto& y = expr;auto* y = expr; ----> auto 关键字后的引用或指针。

警告: const 在此规则中不会被忽略!!! .

int y = 10;
auto& x = y; // The type of variable x is int&.

警告:在此规则中,不会发生数组到指针的转换(数组衰减)!!!。

auto& x = "hello"; // The type of variable x is  const char [6].

static int x = 10;
auto y = x; // The variable y is not static.Because the static keyword is not a type. specifier 
            // The type of variable x is int.

第三条规则

auto&& z = expr; ----> 这不是右值引用。

警告:如果类型推断存在问题并且使用了 && 标记,则名称 像这样引入的称为“转发引用”(也称为通用引用)。

auto&& r1 = x; // The type of variable r1 is int&.Because x is Lvalue expression. 

auto&& r2 = x+y; // The type of variable r2 is int&&.Because x+y is PRvalue expression. 

答案 5 :(得分:3)

它不会去任何地方......它是C ++ 11实现中的新标准C ++特性。话虽这么说,虽然它是一个很好的工具,用于简化对象声明以及清理某些调用范例的语法(即基于范围的for循环),不要过度使用/滥用它: - )

答案 6 :(得分:3)

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

当我们必须使用迭代器时,它可能非常有用。例如对于下面的代码,我们可以简单地使用“ 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”关键字的方式

答案 7 :(得分: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);
}