var i = 10; // 隐式(implicitly)类型定义
int i = 10; // 显式(explicitly)类型定义
auto i = 10;
是不是和 C# 的隐式类型定义很像呢?auto x = 5; // OK: x是int类型 auto pi = new auto(1); // OK: pi被推导为int* const auto *v = &x, u = 6; // OK: v是const int*类型,u是const int类型 static auto y = 0.0; // OK: y是double类型 auto int r; // error: auto不再表示存储类型指示符 auto s; // error: auto无法推导出s的类型在上面的代码示例中:
=6,否则编译器不予通过。u=6.0,编译器将会报错:
const auto *v = &x, u = 6.0;
error: inconsistent deduction for 'const auto': 'int' and then 'double'
auto int i = 0; // C++98/03,可以默认写成 int i = 0;
static int j = 0;
int x = 0; auto * a = &x; // a -> int*,auto被推导为int auto b = &x; // b -> int*,auto被推导为int* auto & c = x; // c -> int&,auto被推导为int auto d = c; // d -> int ,auto被推导为int const auto e = x; // e -> const int auto f = e; // f -> int const auto& g = x; // e -> const int& auto& h = g; // f -> const int&由上面的例子可以看出:
template <typename T> void func(T x) {} // T -> auto
template <typename T> void func(T * x) {} // T * -> auto *
template <typename T> void func(T & x) {} // T & -> auto &
template <typename T> void func(const T x) {} // const T -> const auto
template <typename T> void func(const T * x) {} // const T * -> const auto *
template <typename T> void func(const T & x) {} // const T & -> const auto &
void func(auto a = 1) {} // error: auto不能用于函数参数
struct Foo
{
auto var1_ = 0; // error: auto不能用于非静态成员变量
static const auto var2_ = 0; // OK: var2_ -> static const int
};
template <typename T>
struct Bar {};
int main(void)
{
int arr[10] = {0};
auto aa = arr; // OK: aa -> int *
auto rr[10] = arr; // error: auto无法定义数组
Bar<int> bar;
Bar<auto> bb = bar; // error: auto无法推导出模板参数
return 0;
}
在 Foo 中,auto 仅能用于推导 static const 的整型或者枚举成员(因为其他静态类型在 C++ 标准中无法就地初始化),虽然 C++11 中可以接受非静态成员变量的就地初始化,但却不支持 auto 类型非静态成员变量的初始化。
#include <map>
int main(void)
{
std::map<double, double> resultMap;
// ...
std::map<double,double>::iterator it = resultMap.begin();
for(; it != resultMap.end(); ++it)
{
// do something
}
return 0;
}
观察上面的迭代器(iterator)变量it的定义过程,总感觉有点憋屈。其实通过 resultMap.begin(),已经能够知道 it 的具体类型了,却非要书写上长长的类型定义才能通过编译。
#include <map>
int main(void)
{
std::map<double, double> resultMap;
// ...
for(auto it = resultMap.begin(); it != resultMap.end(); ++it)
{
// do something
}
return 0;
}
再次观察 it 的定义过程,是不是感到清爽了很多?
#include <map>
int main(void)
{
std::unordered_multimap<int, int> resultMap;
// ...
std::pair< std::unordered_multimap<int,int>::iterator, std::unordered_multimap<int, int>::iterator > range = resultMap.equal_range(key);
return 0;
}
这个 equal_range 返回的类型声明显得烦琐而冗长,而且实际上并不关心这里的具体类型(大概知道是一个 std::pair 就够了)。这时,通过 auto 就能极大的简化书写,省去推导具体类型的过程:
#include <map>
int main(void)
{
std::unordered_multimap<int, int> map;
// ...
auto range = map.equal_range(key);
return 0;
}
另外,在很多情况下我们是无法知道变量应该被定义成什么类型的,比如下面的例子。
class Foo
{
public:
static int get(void)
{
return 0;
}
};
class Bar
{
public:
static const char* get(void)
{
return "0";
}
};
template <class A>
void func(void)
{
auto val = A::get();
// ...
}
int main(void)
{
func<Foo>();
func<Bar>();
return 0;
}
在这个例子里,我们希望定义一个泛型函数 func,对所有具有静态 get 方法的类型 A,在得到 get 的结果后做统一的后续处理。若不使用 auto,就不得不对 func 再增加一个模板参数,并在外部调用时手动指定 get 的返回值类型。
版权说明:Copyright © 广州松河信息科技有限公司 2005-2025 版权所有 粤ICP备16019765号
广州松河信息科技有限公司 版权所有