从我用来学习 C++ 的所有材料中,auto
一直是一个奇怪的存储持续时间说明符,没有任何用途。但就在最近,我遇到了将它本身用作类型名称的代码。出于好奇,我尝试了它,它假定我碰巧分配给它的类型!
突然之间,STL 迭代器以及任何使用模板的东西都变得更容易编写了 10 倍。感觉就像我在使用像 Python 这样的“有趣”语言。
我的一生都在哪里?你会说它是视觉工作室独有的还是不便携的,这会打破我的梦想?
auto
是 C++ 从 C 中“继承”的一个关键字,几乎永远存在,但实际上从未使用过,因为只有两种可能的情况:要么是不允许的,要么是默认情况下假定的。
使用auto
to 表示推导类型是 C++11 的新功能。
同时,从类型的auto x = initializer
类型推导类型的方法与模板类型推导对函数模板的工作方式相同。考虑这样的函数模板:x
initializer
template<class T>
int whatever(T t) {
// point A
};
在点 A 处,已T
根据为参数传递的值分配了一个类型 to whatever
。当你这样做auto x = initializer;
时,相同的类型推导用于x
从initializer
用于初始化它的类型中确定类型。
这意味着编译器需要实现的大多数类型推断机制auto
已经存在并用于任何编译器上的模板,甚至尝试实现 C++98/03。因此,对于基本上所有的编译器团队来说,添加对 的支持auto
显然相当容易——它被添加得非常快,而且似乎也几乎没有与之相关的错误。
最初编写此答案时(在 2011 年,在 C++ 11 标准上墨迹未干之前)auto
已经非常便携。如今,它在所有主流编译器中完全可移植。避免它的唯一明显原因是,如果您需要编写与 C 编译器兼容的代码,或者您有特定需要针对某些您知道不支持它的利基编译器(例如,仍然有少数人编写代码对于 MS-DOS,使用 Borland、Watcom 等的编译器,几十年来没有出现重大升级)。如果您使用的是任何主流编译器的合理当前版本,那么完全没有理由避免它。
该标准的最新修订版增加了一些auto
可以使用的新地方。从 C++14 开始,您可以使用auto
lambda 的参数类型:
[](auto s) { return s + 1; }
这与上面的示例基本相同——尽管它没有显式使用template
语法,但这基本上是一个模板,它推断参数的类型,并在该类型上实例化模板。
这非常方便和有用,以至于在 C++20 中,为普通函数添加了相同的功能,而不仅仅是 lambda。
但是,就像以前一样,所有这些实际上都归结为使用自 C++98 以来我们用于函数模板的相同基本类型推导机制。auto
允许它在更多地方使用,更方便,但底层的繁重工作保持不变。
它只是采用一个通常无用的关键字并赋予它一个新的、更好的功能。它在 C++11 中是标准的,大多数甚至支持 C++11 的 C++ 编译器都会支持它。
对于变量,指定要声明的变量的类型将自动从其初始化程序中推导出来。对于函数,指定返回类型是尾随返回类型或将从其返回语句中推导出来(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)
在块作用域、命名空间作用域、for循环的初始化语句等声明变量时,可以使用关键字auto作为类型说明符。
一旦确定了初始化器的类型,编译器就会使用函数调用的模板参数推导规则来确定将替换关键字 auto 的类型(有关详细信息,请参阅模板参数推导#Other contexts)。关键字 auto 可以伴随修饰符,例如 const 或 &,它们将参与类型推导。例如,如果函数调用被编译const auto& i = expr;
,那么 i 的类型正是假想模板中参数 u 的类型。因此,根据初始化程序,auto&& 可以推导出为左值引用或右值引用,用于基于范围的 for 循环。template<class U> void f(const U& u)
f(expr)
如果 auto 用于声明多个变量,则推导的类型必须匹配。例如,声明格式auto i = 0, d = 0.0;
不正确,而声明格式正确auto i = 0, *p = &i;
,并且将 auto 推导出为 int。
在使用尾随返回类型语法的函数声明中,关键字 auto 不执行自动类型检测。它仅用作语法的一部分。
在不使用尾随返回类型语法的函数声明中,关键字 auto 表示将使用模板参数推导规则从其返回语句的操作数推导返回类型。
如果变量的声明类型是decltype(auto)
,则关键字 auto 被替换为其初始值设定项的表达式(或表达式列表),并使用 decltype 的规则推导出实际类型。
如果声明了函数的返回类型decltype(auto)
,则关键字 auto 将替换为其 return 语句的操作数,并使用 decltype 的规则推导出实际的返回类型。
auto:: 形式的嵌套名称说明符是一个占位符,它被遵循约束类型占位符推导规则的类或枚举类型替换。
lambda 表达式中的参数声明。(C++14 起)函数参数声明。(概念 TS)
在 C++11 之前,auto 具有存储持续时间说明符的语义。不允许在一个声明中混合自动变量和函数,如 inauto f() -> int, i = 0;
是不允许的。
您一生都没有此功能。自 2010 版本以来,它已在 Visual Studio 中得到支持。这是一个新的 C++11 功能,因此它不是 Visual Studio 独有的,并且是/将是可移植的。大多数编译器已经支持它。
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”关键字
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.
它不会去任何地方......它是 C++11 实现中的一个新的标准 C++ 功能。话虽如此,虽然它是简化对象声明以及清理某些调用范式(即基于范围的 for 循环)的语法的绝佳工具,但不要过度使用/滥用它:-)
它的神奇之处在于它能够减少为传递给特定函数的每个变量类型编写代码的能力。在它的 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);
}