c++ auto关键字。为什么它是魔法?

从我用来学习c++的所有材料中,auto一直是一个奇怪的存储持续时间指示符,没有任何用途。但就在最近,我遇到了一些代码,它们将它本身用作类型名。出于好奇,我尝试了一下,它假设我分配给它的任何类型!

突然间,STL迭代器,以及任何使用模板的东西都变得容易了10倍。感觉我在使用一种“有趣”的语言,比如Python。

这个关键字在我的生活中哪里呢?你会说这是visual studio独有的或者不能携带的,这会让我的梦想破灭吗?

189182 次浏览

这种功能并不是你一生中就有的。自2010年版本以来,Visual Studio一直支持它。它是c++ 11的一个新特性,所以它不是Visual Studio独有的,并且是可移植的。大多数编译器已经支持它了。

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

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

auto是c++“继承”的关键字。C中几乎一直存在,但实际上从未使用过,因为只有两种可能的情况:要么是不允许,要么是默认假设。

使用auto来表示演绎的类型是c++ 11的新功能。

与此同时,auto x = initializerinitializer的类型中推导出x的类型,这与模板类型推导函数模板的方式相同。考虑这样一个函数模板:

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

在点A,一个类型已经根据参数传递给whatever的值赋值给T。当你执行auto x = initializer;时,会使用相同的类型推断,从用于初始化initializer的类型中确定x的类型。

这意味着编译器实现auto所需的大多数类型演绎机制已经存在,并且用于任何试图实现c++ 98/03的编译器的模板。因此,添加对auto的支持显然对所有编译器团队来说都是相当容易的——它的添加非常快,而且似乎也几乎没有与之相关的错误。

当这个答案最初被写出来的时候(在2011年,在c++ 11标准上的墨水还没有干之前),auto已经是相当可移植的。现在,它在所有主流编译器中都是完全可移植的。避免使用它的唯一明显的原因是,如果你需要编写与C编译器兼容的代码,或者你有特定的需求,针对一些你知道不支持它的利基编译器(例如,一些人仍然使用Borland、Watcom等编译器为MS-DOS编写代码,这些编译器几十年来都没有出现重大升级)。如果您正在使用任何主流编译器的合理当前版本,则完全没有理由避免使用它。

该标准最近的修订增加了一些可以使用auto的新地方。从c++ 14开始,你可以使用auto作为lambda的形参类型:

    [](auto s) { return s + 1; }

这在本质上与上面的例子所做的事情相同——即使它没有显式地使用template语法,这基本上是一个推断形参类型的模板,并在该类型上实例化模板。

这是非常方便和有用的,以至于在c++ 20中,为普通函数添加了相同的功能,而不仅仅是lambdas。

但是,就像之前一样,所有这些都归结为使用与c++ 98以来的函数模板相同的基本类型推断机制。auto允许在更多的地方使用,更方便,但底层的繁重工作保持不变。

对于变量,指定要声明的变量的类型将自动从其初始化式推导出来。对于函数,指定返回类型是尾随返回类型或将从其返回语句中推导出(自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的类型(详情请参阅模板实参推断#其他上下文)。关键字auto可能伴随着修饰符,例如const或&,它们将参与类型推断。例如,给定const auto& i = expr;,如果编译了函数调用f(expr),则i的类型恰好是虚构模板template<class U> void f(const U& u)中的实参u的类型。因此,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将被其返回语句的操作数替换,并且使用decltype规则推导出实际的返回类型。

  6. auto::形式的嵌套名称说明符是一个占位符,由遵循约束类型占位符演绎规则的类或枚举类型替换。

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

笔记

直到c++ 11, auto都有存储持续时间指示符的语义。 在一个声明中混合自动变量和函数,如auto f() -> int, i = 0;是不允许的

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

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”关键字

它的神奇之处在于它能够减少为传递到特定函数的每个变量类型编写代码。考虑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);
}

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

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

第一条规则

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

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.