之前老师上课的时候,输了这么一行代码: vector<int> ve; for(auto x:ve){ do sth; } 这里的auto是干啥?

C++ 关键字auto[1]

目录

目录

  • C++ 关键字auto[1]
  • 目录
  • c++98 auto
  • c++11 auto
  • auto使用注意事项
  • (1)auto 变量必须在定义时初始化,这类似于const关键字;
  • (2)定义在一个auto序列的变量必须始终推导成同一类型,如:
  • (3)如果初始化表达式是引用,则去除引用语义,如:
  • (4)如果初始化表达式为const或volatile(或者两者兼有),则除去const/volatile语义。
  • (5)如果auto关键字带上&号,则不去除const语义。
  • (6)初始化表达式为数组时,auto关键字推导类型为指针。
  • (7)如果表达式为数组且auto带上&,则推导类型为数组类型。
  • (8)函数或模板参数不能被声明为auto。
  • (9)auto不是一个真正的类型,仅仅是一个占位符,不能使用一些以类型为操作数的操作符,如sizeof或typeid:

c++98 auto

早在C++98标准中就存在了auto关键字,那时的auto用于声明变量为自动变量,拥有自动的生命周期;但是该作用是多余的,变量默认拥有自动的生命周期。

int a = 10;      // 自动生命周期
auto int b = 20; // 自动生命周期

在C++ 11 中,已经删除了该用法,取而代之的作用是:自动推断变量的类型。

c++11 auto

auto可以在声明变量的时候根据变量初始值的类型自动为此变量选择匹配的类型:

auto i =100;  // i 是 int 
auto p = new A();  // p 是 A* 
auto k = 34343LL;  // k 是 long long

这种用法就类似于C#中的var关键字。auto的自动类型推断发生在编译期,所以使用auto并不会造成程序运行时效率的降低。是否会造成编译期的时间消耗,我认为是不会的,在未使用auto时,编译器也需要得知右操作数的类型,再与左操作数的类型进行比较,检查是否可以发生相应的转化,是否需要进行隐式类型转换。

对于上面的示例,在实际编程中并不推荐,因为不便于他人阅读,直接写出变量的类型会更加的清晰易懂,主要用于代替冗长复杂,变量使用范围专一的变量声明,比如:

std::vector<std::string> vec;
for (auto iter = vec.begin(); iter != vec.end(); ++iter) {}

在定义函数模板时,用于声明依赖模板参数的变量类型,模板函数依赖于模板参数的返回值:

template<typename Tx, typename Ty>
auto multiply(Tx x, Ty y)          // c++14
{
    return x * y;
}

auto使用注意事项

(1)auto 变量必须在定义时初始化,这类似于const关键字;

(2)定义在一个auto序列的变量必须始终推导成同一类型,如:

auto a = 1, b = 2, c = 3;     // 正确
auto a = 1, b = 2.2, c = 'c'; // 错误(这个道理和第一点注意事项相同)

(3)如果初始化表达式是引用,则去除引用语义,如:

int  a = 1;
int &b = a;

auto  c = b; // 此时c的类型被推导为 int32,而不是int32&
auto &c = b; // 此时c的类型才是int&

(4)如果初始化表达式为const或volatile(或者两者兼有),则除去const/volatile语义。

const int a = 10;
auto  b= a;         // b的类型为int而非const int(去除const)
const auto c = a;   // 此时c的类型为const int

b = 100;   // 合法
c = 100;   // 非法

(5)如果auto关键字带上&号,则不去除const语义。

const int a = 10;
auto &b = a;    // 因为auto带上&,故不去除const,b类型为const int

b = 10;   /非法

(6)初始化表达式为数组时,auto关键字推导类型为指针。

int a[3] = { 1, 2, 3 };
auto b = a;

std::cout << typeid(b).name() << std::endl;   // 这里输出 int*

(7)如果表达式为数组且auto带上&,则推导类型为数组类型。

int a[3] = { 1, 2, 3 };
auto &b = a;

std::cout << typeid(b).name() << std::endl; // 这里输出 int[3]

(8)函数或模板参数不能被声明为auto。

void func(auto a)  // 错误
{
    //... 
}

(9)auto不是一个真正的类型,仅仅是一个占位符,不能使用一些以类型为操作数的操作符,如sizeof或typeid:

std::cout << sizeof(auto) << std::endl;        // 错误
std::cout << typeid(auto).name() << std::endl; // 错误

  1. src=http://suo.im/67P9DK ↩︎