自动推导类型auto
在C++11之前,auto
关键字用于指定变量的存储期,但在C++11中,它的功能被改为类型推导。
auto
现在成了一个类型的占位符,它告诉编译器查看变量的初始化器表达式,并使用该表达式的类型来确定变量的类型。这对于避免编写冗长的类型名称,特别是涉及模板的类型名称,非常有用。
在没有auto
之前,遍历一个容器可能需要以下书写一个迭代器:
cpp
vector<int> vec = {1,2,3,4,5};
for(vector<int>::iterator it = vec.begin(); it != vec.end(); it++){
cout << *it << endl;
}
当有了auto
之后,可以使用以下代码:
cpp
vector<int> vec = {1,2,3,4,5};
for(auto it = vec.begin(); it != vec.end(); it++){
cout << *it << endl;
}
auto 与 const 和引用的交互
当auto
与const
和引用结合使用时,auto
的行为可能会引起一些困惑。下面来看几个示例:
cpp
int x = 0;
const auto n = x; // 第2行
auto f = n; // 第3行
const auto& r1 = x; // 第4行
auto& r2 = r1; // 第5行
第二行 const auto n = x;
- x 是一个
int
类型 - 由于我们使用了
const
修饰符,所以n
的类型为const int
- 这里的
auto
被推导为int
,然后应用前面的const
修饰符
第3行 :auto f = n;
- 尽管
n
是一个const int
类型,但当我们使用auto
进行类型推导时,const
修饰符不会被考虑。 - 因此
f
的类型为int
第4行 :const auto& r1 = x;
- x 是一个
int
类型 - 由于我们使用了
const
和引用&
,所以r1
的类型为const int &
- 这里的
auto
被推导为int
,然后应用了const
和引用&
修饰符
第5行 :auto& r2 = r1;
r1
是const int&
类型。- 但当我们使用
auto&
进行类型推导时,const
修饰符会被考虑。 - 因此,
r2
的类型也是const int&
。
总结
- 当类型不为引用时,使用
auto
进行类型推导将不保留 表达式的const
属性。 - 当类型为引用时,使用
auto
进行类型推导将保留 表达式的const
属性。
auto 的高级用法
auto
除了可以独立使用,还可以与某些具体的类型混合使用,这样auto
表示的就是"半个"类型,而不是完整的类型,从而使得类型推导更灵活。下面给出一些示例:
cpp
int x = 0;
auto *pt1 = &x; //pt1 为 int *,auto 推导为 int
auto pt2 = &x; //pt2 为 int*,auto 推导为 int*
auto &r1 = x; //r1 为 int&,auto 推导为 int
auto r2 = r1; //r2 为 int,auto 推导为 int
分析:
auto \*pt1 = &x;
:&x
取得的是变量x
的地址,其类型是int*
。auto
前面有一个*
,所以auto
被推导为int
,与*
结合后,pt1
的类型为int*
。
auto pt2 = &x;
:- 同样,
&x
取得的是x
的地址,其类型是int*
。 - 由于没有任何其他修饰符,
auto
直接被推导为int*
,所以pt2
的类型是int*
。
- 同样,
auto &r1 = x;
:x
的类型是int
。auto
前面有一个&
,因此auto
被推导为int
,与&
结合后,r1
的类型为int&
。
auto r2 = r1;
:r1
是一个引用,其引用的是int
类型。- 由于没有其他修饰符,
auto
直接被推导为int
,所以r2
的类型是int
。
auto的限制
-
不能在函数参数中使用
auto
。cppvoid myFunction(auto param) { // 错误! //... }
-
不能将
auto
用于类的非静态成员变量。cppclass MyClass { auto myVar = 10; // 错误! };
就是没有static关键字修饰的成员变量
-
不能将
auto
用于模板参数。cpptemplate<auto T> // 错误! class MyTemplateClass { // ... };
-
不能用于推导数组类型。
cppint main() { int arr[] = {1, 2, 3, 4, 5}; auto arr2 = arr; // 错误! }
但可以通过引用的方式来推导:
cppint main() { int arr[] = {1, 2, 3, 4, 5}; auto& arr2 = arr; // 正确!arr2是对arr的引用 }
decltype
decltype
是"declared type"的缩写,意为"声明的类型"。与sizeof
操作符类似,decltype
评估表达式的类型,但不实际计算表达式的值。
decltype
,在C++中,用于查询表达式的数据类型的操作符,该操作不是实际执行该表达式。这个特性在泛型编程和模板元变成中尤其有用,以解决由于有些类型有模板参数决定,而难以(甚至是不能)表达式的问题。
于auto
不同的是,auto
关键字允许对变量的类型进行自动推导,它主要是基于变量的初始化表达式来工作的。decltype
允许我们基于任何给定的表达式来查询类型,而不仅仅是初始化表达式。
对于lambda表达式,如果我们想要在其他地方使用它的类型,我们需要decltype
。