C++11 new features distinguish and relate auto and decltype

  • 2020-05-12 02:59:30
  • OfStack

C++11 new features distinguish and relate auto and decltype

1. auto profile

When programming, you often need to pay the value of the expression to the variable, and you need to know exactly what type the variable is when you declare it. However, this is not always easy to do (especially in templates), and sometimes not at all. To solve this problem, the new C++11 standard introduces the auto type specifier, which allows the compiler to analyze the type of the expression for us. Unlike the original ones, which only correspond to a specific type specifier, such as int. auto lets the compiler perform type deduction with initial values. To get the type of the defined variable, the variable defined by auto must have an initial value.


// by val_1  and val_2 The sum can be inferred item The type of  
auto item = val_1 + val_2;//item  The type is initialized to val_1 + val_2 The added type , A value of val_1+val_2 The sum of the values.  

The item type here is calculated by the compiler during compilation by adding the val_1 and val_2 types. If it is val_1(int) + val_2(double), then the type of item is double.

It is also possible to declare multiple variables in one statement using auto, since one declaration rain gear can only have one basic data type, so the initial basic data type of all the variables of the rain gear must be one. Here you must distinguish between a data type and a type modifier!!


int i = 3; 
auto a = i,&b = i,*c = &i;// correct : a Initialized to i A copy of the ,b Initialized to i A reference to the ,c for i A pointer to the . 
auto sz = 0, pi = 3.14;// error , The types of the two variables are not 1 The sample.  

The type of auto inferred by the compiler is sometimes 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.

First, as we all know, using a reference is really about using the object that is referenced, especially when the reference is used as an initial value, and what is really involved in the initialization is the value of the reference object. At this point, the compiler takes the type of the reference object as the type of auto:


int i = 0 ,&r = i;// define 1 An integer i, And define r for i The application of . 
auto a = r; // Here, a As for the 1 An integer , It's going to be the same thing as this i1 sample . 

It can be seen that auto ignores references. Secondly, auto1 generally ignores the top level const, but the bottom level const is retained, for example, when the initial value is a pointer to a constant:


int i = 0; 
const int ci = i, &cr = ci; //ci  Is an integer constant ,cr  Is a reference to an integer constant   
auto a = ci;   // a  for 1 An integer ,  At the top const Be ignored  
auto b = cr;   // b  for 1 Integers, top level const Be ignored  
auto c = &ci;  // c  for 1 Integer pointer . 
auto d = &cr;  // d  for 1 A pointer to an integer constant ( The region address for the constant object is that const It becomes the bottom layer const) 

If you wish to infer that the auto type is a top level const, you need to specify:


const auto f = ci; 

You can also set the type of the reference to auto, where the original initialization rules still apply (const for reference declarations are all low-level const) :


auto &g = ci; //g is 1 Two integer constant references, bound to ci .  
auto &h = 42; //  Error: the initial value of the nonconstant reference must be an lvalue.  
const auto &j = 42; // correct : Constant references can be bound to literals.   

2. decltype profile

Sometimes we have situations where we want to infer the type of variable to be defined from the expression, but we don't want to initialize the variable with the value of the expression. It could also be that the return type of a function is the value type of an expression. auto becomes weak at these times, so C++11 introduces a second type specifier, decltype, which selects and returns the operand's data type. In doing so, the compiler simply analyzes the expression and gets its type, but does not actually evaluate the expression.


decltype(f()) sum = x;// sum The type of theta is a function f Type of return value.  

Here the compiler does not actually call the f function, but instead analyzes the return value of the f function as the sum definition type.

Basically, decltype is very similar to auto, so I'm not going to list 11. Another use for decltype is the post-return type introduced in c++11.

3. The difference between decltype and auto

decltype handles top-level const and references in a slightly different way from auto. If the expression decltype USES is a variable, decltype returns the type of that variable (including top-level const and references).


const int ci = 42, &cj = ci; 
 
decltype(ci) x = 0;  // x  A type of const int 
auto z = ci;     // z  A type of int 
 
decltype(cj) y = x;  // y  A type of const int& 
auto h = cj;     // h  A type of int 

decltype has a few other notable points, but let's take a look at the following code:


int i = 42, *p = &i, &r = i; 
 
decltype(i) x1 = 0;    // because  i  for  int , so  x1  for int 
auto x2 = i;       // because  i  for  int , so  x2  for int 
 
decltype(r) y1 = i;    // because  r  for  int& , so  y1  for int& 
auto y2 = r;       // because  r  for  int& , but auto The reference is ignored, so  y2  for int 
 
decltype(r + 0) z1 = 0;  // because  r + 0  for  int , so  z1  for int, 
auto z2 = r + 0;     // because  r + 0  for  int , so  z2  for int, 
 
decltype(*p) h1 = i;   // Here,  h1  is int& .   And the reason for that  
auto h2 = *p;       // h2  for  int. 

If the content of the expression is a dereferencing operation, decltype gets the reference type. As we are familiar with, a dereferencing pointer can get the pointer to an object, and it can also assign a value to that object. So the result type of decltype(*p) is int&.

Another important difference between decltype and auto is that the result type of decltype is closely related to the form of expression. One thing to note in particular is that for the expressions used by decltype, if the variable name is bracketed with 1, the resulting type may be different than it would have been without the brackets. If decltype USES an unbracketed variable, the result is the type of the variable. But if you add one or more parentheses to the variable, the compiler will treat the variable as an expression, a special expression that can be used as an lvalue, so this decltype will return the reference type:


int i = 42; 
 
//decltype(i)  int  type  
//decltype((i)) int&  type  

One more thing to note here is that the = assignment operator returns a reference to the lvalue. In other words, decltype(i = b) returns a reference of type i. Take a closer look at this code:


int i = 3; 
auto a = i,&b = i,*c = &i;// correct : a Initialized to i A copy of the ,b Initialized to i A reference to the ,c for i A pointer to the . 
auto sz = 0, pi = 3.14;// error , The types of the two variables are not 1 The sample.  
0

The running result is:


int i = 3; 
auto a = i,&b = i,*c = &i;// correct : a Initialized to i A copy of the ,b Initialized to i A reference to the ,c for i A pointer to the . 
auto sz = 0, pi = 3.14;// error , The types of the two variables are not 1 The sample.  
1

As you can see from the above code and the results, the assignment statement in 1.decltype (i = 41) does not actually run. 2. decltype(i = 41) returns int&, which means that x is actually a reference to i.

After learning about auto and decltype, I will make sure to distinguish the difference between them in the process of using const and const, so as to prevent the difference between const and const and between reference and non-reference in the definition!!

Thank you for reading, I hope to help you, thank you for your support of this site!


Related articles: