文章目录
C++ | C++ 11 Auto 类型推导
在 C++11 之前的版本(C++98 和 C++ 03)中,定义变量或者声明变量之前都必须指明它的类型,比如 int
、char
等;但是在一些比较灵活的语言中,比如 C#、JavaScript、PHP、Python 等,程序员在定义变量时可以不指明具体的类型,而是让编译器(或者解释器)自己去推导,这就让代码的编写更加方便。
后续,C++11 使用 auto 关键字来支持自动类型推导。
auto
类型推导的语法和规则
C++11 赋予 auto
关键字新的含义,使用它来做自动类型推导。使用auto
关键字后,编译器会在编译期间自动推导出变量的类型。
auto name = value; // name是变量名,value是变量初始值
注意:auto
仅仅是一个占位符,在编译器期间它会被真正的类型所替代。或者说,C++ 中的变量必须是有明确类型的,只是这个类型是由编译器自己推导出来的。
实例1
auto n = 10;
auto f = 12.8;
auto p = &n;
auto url = "http://www.baidu.com/";
- 第 1 行中,10 是一个整数,默认是
int
类型,所以推导出变量n
的类型是int
。 - 第 2 行中,12.8 是一个小数,默认是
double
类型,所以推导出变量f
的类型是double
。 - 第 3 行中,
&n
的结果是一个int*
类型的指针,所以推导出变量p
的类型是int*
。 - 第 4 行中,由双引号
""
包围起来的字符串是const char*
类型,所以推导出变量url
的类型是const char*
,也即一个常量指针。
实例2(连续定义多个变量)
int n = 20;
auto *p = &n, m = 99;
20是一个整数,所以推导出n
是int
型。而&n
是int *
类型。编译器会根据auto *p
推导出auto
为int型。所以变量m
就是int
类型的。
**注意:**推导的时候不能有二义性。在本例中,编译器根据第一个子表达式已经推导出 auto
为 int
类型,那么后面的 m
也只能是 int
类型,如果写作m=12.5
就是错误的,因为 12.5 是double
类型,这和 int
是冲突的。
还有一个值得注意的地方是:使用 auto
类型推导的变量必须马上初始化,这个很容易理解,因为 auto
在 C++11 中只是“占位符”,并非如 int
一样的真正的类型声明。
auto
的高级用法
auto
除了可以独立使用,还可以和某些具体类型混合使用,这样 auto
表示的就是“半个”类型,而不是完整的类型。
实例3
int x = 0;
auto *p1 = &x; //p1 为 int *,auto 推导为 int
auto p2 = &x; //p2 为 int*,auto 推导为 int*
auto &r1 = x; //r1 为 int&,auto 推导为 int
auto r2 = r1; //r2 为 int,auto 推导为 int
- 第 2 行代码中,
p1
为int*
类型,也即auto *
为int *
,所以auto
被推导成了int
类型。 - 第 3 行代码中,
auto
被推导为int*
类型。 - 第 4 行代码中,
r1
为int &
类型,auto
被推导为int
类型。 - 第 5 行代码是需要重点说明的,
r1
本来是int&
类型,但是auto
却被推导为int
类型,这表明当=
右边的表达式是一个引用类型时,auto
会把引用抛弃,直接推导出它的原始类型。
示例4(auto
和const
的结合)
int x = 0;
const auto n = x; // n 为 const int ,auto 被推导为 int
auto f = n; // f 为 const int,auto 被推导为 int(const 属性被抛弃)
const auto &r1 = x; // r1 为 const int& 类型,auto 被推导为 int
auto &r2 = r1; // r1 为 const int& 类型,auto 被推导为 const int 类型
-
第 2 行代码中,
n
为const int
,auto
被推导为int
。 -
第 3 行代码中,
n
为const int
类型,但是auto
却被推导为int
类型,这说明当=
右边的表达式带有const
属性时,auto
不会使用const
属性,而是直接推导出non-const
类型。 -
第 4 行代码中,
auto
被推导为int
类型。 -
第 5 行代码中,
r1
是const int &
类型,auto
也被推导为const int
类型,这说明当const
和引用结合时,auto
的推导将保留表达式的const
类型。 -
当类型不为引用时,auto 的推导结果将不保留表达式的 const 属性;
-
当类型为引用时,auto 的推导结果将保留表达式的 const 属性。
auto
的限制
使用 auto
的时候必须对变量进行初始化,这是 auto
的限制之一。
-
auto
不能在函数的参数中使用。 -
auto
不能作用于类的非静态成员变量(也就是没有static
关键字修饰的成员变量)中。 -
auto
关键字不能定义数组。 -
auto
不能作用于模板参数。
实例5(不能定义数组)
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
char url[] = "www.baidu.com";
auto str[] = url; // ERR:‘str’ declared as array of ‘auto’
return 0;
}
实例6(不能作用于模板参数)
/*******************************************************************
* > File Name: auto-test2.cpp
* > Create Time: 2021年10月 8日 21:42:55
******************************************************************/
#include <iostream>
using namespace std;
template <typename T>
class A{
//TODO:
};
int main(int argc, char* argv[])
{
A<int> C1;
A<auto> C2 = C1; // ERR:‘auto’ not permitted in template argument
return 0;
}
auto 的应用
使用 auto 定义迭代器
实例7
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
vector<vector<int>> v;
vector<vector<int>>::iterator i = v.begin();
return 0;
}
改进版
/*******************************************************************
* > File Name: auto-test4.cpp
* > Create Time: 2021年10月 8日 21:50:58
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<vector<int>> v;
auto i = v.begin();
return 0;
}
auto
可以根据表达式 v.begin()
的类型(begin()
函数的返回值类型)来推导出变量 i
的类型。
auto 用于泛型编程
实例8
/*******************************************************************
* > File Name: auto-test5.cpp
* > Create Time: 2021年10月 8日 21:56:54
******************************************************************/
#include <iostream>
using namespace std;
class A{
public:
static int get(void){
return 100;
}
};
class B{
public:
static const char *get(void){
return "www.baidu.com";
}
};
template <typename T>
void func(void){
auto val = T::get();
cout << val << endl;
}
int main(int argc, char* argv[])
{
func<A>();
func<B>();
return 0;
}
编译、运行:
g++ -o auto-test5 auto-test5.cpp -g -Wall -std=c++11
PS D:\study\cplusplus\day14> .\auto-test5.exe
100
www.baidu.com
实例9
不使用auto
的方法。
/*******************************************************************
* > File Name: auto-test6.cpp
* > Create Time: 2021年10月 8日 22:05:14
******************************************************************/
#include <iostream>
using namespace std;
class A{
public:
static int get(void){
return 100;
}
};
class B{
public:
static const char *get(void){
return "www.baidu.com";
}
};
template<typename T1, typename T2>
void func(void){
T1 val = T2::get();
cout << val << endl;
};
int main(int argc, char* argv[])
{
func<int, A>();
func<const char*, B>();
return 0;
}
编译、运行:
g++ -o auto-test6 auto-test6.cpp -g -Wall -std=c++11
PS D:\study\cplusplus\day14> .\auto-test6.exe
100
www.baidu.com