C++ auto keyword

C ++ 98 auto

As early as in the C++98 standard, the auto keyword existed. At that time, auto was used to declare variables as automatic variables. Automatic variables meant to have automatic lifetimes. This was redundant, because even if auto declarations were not used, variables Still have an automatic lifetime:

int a =10 ;  //拥有自动生命期
auto int b = 20 ;//拥有自动生命期
static int c = 30 ;//延长了生命期

The auto in C++98 is redundant and rarely used. C++11 has removed this usage and replaced it with a brand new auto: automatic type inference of variables.

back to the top

C ++ 11 cars

Auto can automatically select the matching type for this variable according to the type of the initial value of the variable when declaring the variable. Similar keywords include decltype. for example:

    int a = 10;
    auto au_a = a;//自动类型推断,au_a为int类型
    cout << typeid(au_a).name() << endl;

The typeid operator can output the type of the variable. The results of the program are output

int

This usage is similar to the var keyword in C#. Auto's automatic type inference occurs at compile time, so the use of auto will not reduce the efficiency of the program at runtime. And whether it will cause time consumption during compilation, I think it will not. When auto is not used, the compiler also needs to know the type of the right operand, and then compare it with the type of the left operand to check whether the corresponding can occur The conversion, whether implicit type conversion is required.

back to the top

The usage of auto

The example cited above is very simple. It is not recommended to use auto in this way when programming. It is more clear and understandable to write the type of the variable directly. The correct usage of the auto keyword is listed below.

Used to replace lengthy and complex variable declarations with specific scope of use.

Imagine that when there is no auto, we often need to operate the standard library like this:

#include<string>
#include<vector>
int main()
{
    std::vector<std::string> vs;
    for (std::vector<std::string>::iterator i = vs.begin(); i != vs.end(); i++)
    {
        //...
    }
}

It's really annoying to look at code and write code in this way. Someone might say why not use using namespace std directly, so the code can be shorter. In fact, this is not the recommended method (C++Primer has a related description of this). Using auto can simplify the code:

#include<string>
#include<vector>
int main()
{
    std::vector<std::string> vs;
    for (auto i = vs.begin(); i != vs.end(); i++)
    {
        //..
    }
}

The i in the for loop will automatically deduce its type at compile time, without us having to explicitly define the long string.

When defining a template function, it is used to declare variable types that depend on template parameters.

template <typename _Tx,typename _Ty>
void Multiply(_Tx x, _Ty y)
{
    auto v = x*y;
    std::cout << v;
}

If you don't use the auto variable to declare v, then this function will be difficult to define. When it is not compiled, who knows the true type of x*y?

The template function depends on the return value of the template parameter

template <typename _Tx, typename _Ty>
auto multiply(_Tx x, _Ty y)->decltype(x*y)
{
    return x*y;
}

When the return value of a template function depends on the parameters of the template, we still cannot determine the type of the template parameter before compiling the code, so we have no way of knowing the type of the return value. In this case, we can use auto. The format is shown above.
The decltype operator is used to query the data type of expressions. It is also a new operator introduced by the C++11 standard. Its purpose is to solve the problem that some types in generic programming are determined by template parameters and are difficult to express.
The role of auto here is also called return value occupancy , it just occupies a place for the function return value, the real return value is the following decltype(_Tx*_Ty). Why do you want to post the return value? If there is no postfix, the function declaration is:

decltype(x*y)multiply(_Tx x, _Ty y)

At this time, x and y have not been declared yet, and the compilation fails.

back to the top

Precautions

  • The auto variable must be initialized when it is defined, which is similar to the const keyword.
  • Variables defined in an auto sequence must always be deduced to the same type. E.g:

    auto a4 = 10, a5 = 20, a6 = 30;//正确
    auto b4 = 10, b5 = 20.0, b6 = 'a';//错误,没有推导为同一类型
    When using the auto keyword for automatic type derivation, the following rules are applied in turn:
  • If the initialization expression is a reference, the reference semantics are removed.

    int a = 10;
    int &b = a;
    
    auto c = b;//c的类型为int而非int&(去除引用)
    auto &d = b;//此时c的类型才为int&
    
    c = 100;//a =10;
    d = 100;//a =100;
  • If the initialization expression is const or volatile (or both), remove the const/volatile semantics.

    const int a1 = 10;
    auto  b1= a1; //b1的类型为int而非const int(去除const)
    const auto c1 = a1;//此时c1的类型为const int
    b1 = 100;//合法
    c1 = 100;//非法
  • If the auto keyword is accompanied by an ampersand, the const semantics is not removed.

    const int a2 = 10;
    auto &b2 = a2;//因为auto带上&,故不去除const,b2类型为const int
    b2 = 10; //非法
    This is because how to remove the const, then b2 is a non-const reference to a2, and the value of a2 can be changed through b2, which is obviously unreasonable.
  • When the initialization expression is an array, the auto keyword deduces the type to be a pointer.

    int a3[3] = { 1, 2, 3 };
    auto b3 = a3;
    cout << typeid(b3).name() << endl;

    The program will output

    int *

  • If the expression is an array and auto is accompanied by &, the deduced type is an array type.

    int a7[3] = { 1, 2, 3 };
    auto & b7 = a7;
    cout << typeid(b7).name() << endl;

    Program output

    int [3]

  • Function or template parameters cannot be declared as auto

    void func(auto a)  //错误
    {
    //... 
    }
  • Always be aware that auto is not a real type.
    Auto is just a placeholder. It is not a real type. You cannot use some type-operand operators, such as sizeof or typeid.

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

Guess you like

Origin blog.csdn.net/hn_tzy/article/details/104746360