C++ auto type descriptor

  • 2020-05-09 18:57:56
  • OfStack

Programming often involves assigning the value of an expression to a variable, which requires that you know the type of the expression when you declare the variable. However, it is not so easy to achieve this point, and sometimes even impossible. To solve this problem, the C++11 standard introduces the auto type descriptor, which allows the compiler to analyze the type of the expression for us.

Unlike the original specifiers, which correspond to only one specific type, auto lets the compiler extrapolate variable types from initial values. Obviously, the variables defined by auto must have an initial value.

Using auto has the following benefits:

Reliability: it also works if the type of the expression changes, including if the return value of the function changes.
Performance: ensures that the conversion will not take place.
Usability: don't worry about spelling type names and spelling errors.
Efficiency: code becomes more efficient.


auto item = val1 + val2; //  by val1 and val2 The sum is inferred item The type of 
auto i=0, *p = &i; // i Is an integer, p It's an integer pointer 

You can declare multiple variables in one statement using auto. However, a declaration statement can only have one basic data type, so the initial basic data type of all variables in this statement must be 1 to:


auto sz = 0, pi = 3.14; // Error!

Sometimes the type of auto inferred by the compiler is not exactly the same as the type of the initial value, and the compiler will appropriately change the result type to make it more consistent with the initialization rules, for example:

Using auto removes references


int count = 10;
int& countRef = count;
auto myAuto = countRef;

countRef = 11;
cout << count << " "; // print 11

myAuto = 12;
cout << count << endl; // print 11

You might think myAuto is an int reference, but it's not. It's just one int, because the output is 11, 11, not 11, 12; This occurs if auto has not deleted this reference.

const qualifiers
First, a statement is introduced: the top level const means that the pointer itself is a constant, and the bottom level const means that the object referred to by the pointer is a constant. 1 general auto will ignore the top level const, while the bottom level const will remain, for example:


int i = 0;
const int ci = i, &cr = ci;
auto b = ci; // b  is 1 An integer ( ci The top of the const Features are ignored) 
auto c = cr; // c  is 1 An integer ( cr is ci The alias, ci Itself is 1 A top const ) 
auto d = &i; // d  is 1 Integer pointer (the address of an integer is the pointer to an integer) 
auto e = &ci; // e  is 1 A pointer to an integer constant 1 Of the underlying const ) 

If you want to infer that the auto type is 1 top-level const, you need to specify:


const auto f = ci; // ci  The type of deduction is int . f is const int type 

You can also set the type of the reference to auto, where the original initialization rules still apply:


auto &g = ci; // g is 1 Integer constant references, bound to ci
auto &h = 42; // Error:  You cannot bind literals for nonconstant references 
const auto &j = 42; // OK:  Literals can be bound for constant references 

Remember, the symbols * and & are subordinate to a declaration only, not part 1 of the basic data type, so the initial values must be of the same type 1:


auto k = ci, &l = i; // k Is an integer, l Is an integer reference 
auto &m = ci, *p = &ci; // m Is a reference to an integer constant, p Is a pointer to an integer constant 
auto &n = i, *p2 = &ci; // Error: i Is of type int And the &ci Is of type const int

More sample code is attached:

The following statement is equivalent. In the first statement, declare the variable j as type int. In the second statement, the variable k is derived as type int, because the initialization expression (0) is an integer


int j = 0; // Variable j is explicitly type int.
auto k = 0; // Variable k is implicitly type int because 0 is an integer.

The following declaration is equivalent, but the second declaration is simpler than the first. One of the most compelling reasons to use the auto keyword is simplicity


map<int,list<string>>::iterator i = m.begin(); 
auto i = m.begin(); 

Start the loop using iter and elem


#include <deque>
using namespace std;

int main()
{
  deque<double> dqDoubleData(10, 0.1);

  for (auto iter = dqDoubleData.begin(); iter != dqDoubleData.end(); ++iter)
  { /* ... */ }

  // prefer range-for loops with the following information in mind
  // (this applies to any range-for with auto, not just deque)

  for (auto elem : dqDoubleData) // COPIES elements, not much better than the previous examples
  { /* ... */ }

  for (auto& elem : dqDoubleData) // observes and/or modifies elements IN-PLACE
  { /* ... */ }

  for (const auto& elem : dqDoubleData) // observes elements IN-PLACE
  { /* ... */ }
}

The following code snippet USES the new operator and pointer declaration to declare Pointers


auto sz = 0, pi = 3.14; // Error!
0

The next code snippet declares multiple symbols in each declaration statement. Note that all symbols in each statement are resolved to the same type 1.


auto sz = 0, pi = 3.14; // Error!
1

This code snippet USES the conditional operator (? :) declare the variable x as an integer with a value of 200:


auto sz = 0, pi = 3.14; // Error!
2

The following code snippet initializes the variable x as type int, the variable y as a reference to type const int, and the variable fp as a pointer to a function that returns type int.


int f(int x) { return x; }
int main()
{
  auto x = f(0);
  const auto & y = f(1);
  int (*p)(int x);
  p = f;
  auto fp = p;
  //...
}


Related articles: