[Effective modern C + + (11&14)] Chapter 2:auto

Source: Internet
Author: User

1. More use Auto instead of explicit type declaration
  • Reduce large segment declarations to auto
    • For example:
      TypeName Std::iterator_traits<it>::value_type currvalue = *= *b;
  • Use Auto to prevent variables from being initialized
    • For example:
      int // correct, but not initialized // error, no initialization 3 // correct, declare and initialize
  • Automatic type deduction of variables can be done using auto in the template function
    • For example:

      Template<typename it>void  dwim (it B, it e) {     for(; b!=e; + +b     )          {  = *b;          ...     }   }
  • Using auto to infer the return result type of a lambda expression
    • For example:

      Auto derefless = [] (constconstreturn *p1 < *p2;};

    • In contrast, using a function object to hold the above results, the code is as follows:

      std::function<BOOL(constconst
         Derefupless = [] (constconstreturn *p1 < *p2;};
    • The difference between these two forms of expression is:

      • Auto declares a variable that occupies the same large memory space as the lambda expression

      • A variable declared with Std::function is a fixed-size space for any function, and if there is not enough space, it will request memory on the heap to store the closure. In addition, because the restriction is inline, the function object has to produce an indirect function call.

      • The result: The Std::function object typically uses more memory and is slower to execute than auto.

  • Use Auto to avoid "type shortcuts"
    • For example:

      std::vector<int>= v.size ();//V.size () The return value type is Std::vector<int>::size_type, Specifies a type of unsigned integer

      The above code is on 32-bit Windows, unsigned and Std::vector<int>::size_type are 32-bit, but on 64-bit Windows, unsigned is 32-bit and std::vector< Int>::size_type is a 64-bit, so running the same code on different machines can be an error, and this should not be the case with a strong coupling to the underlying system.

    • Therefore, the correct usage is as follows:
  • Use Auto to declare variables to avoid the additional cost of implicit conversions when type mismatches are present
    • For example:

       std::unordered_map<std::string , int  > m; ....  for  (const  std::p air<std::string , int  >& P:m) {...  //  do somethins with P } 

      The problem with the above code is that the key part of STD::UNORDERED_MAP is the const attribute, so STD in the hash table::p air type should actually be std::p air<const std::string, int>. However, the above loop declares a const std::p air<std::string, Int> So the compiler has to do a conversion in both types, first to get an std::p air<std::string, int , the compiler needs to copy each object one at a time from M, create a series of temporary variables, then bind these temporary variables to reference p, and then the temporary variables are destroyed by the compiler at the end of the loop.

    • The right approach should be:

       for Const auto& p:m) {    // as before}
  • Recommendations for code readability:
    • If you use display type declarations to make your code clearer and easier to maintain, you should use a display type declaration, or you should try to use auto

    • Variables declared through auto, if you want to make it easy to get what type, you can indirectly represent the type by naming the rules.

2. Use explicit type initialization when auto infers the error type
  • When the type returned by an expression is a type of a proxy class, you cannot use auto
    • Example 1:
      std::vector<bool> features (const widget& W);//Extract the features of the Widget object and vector<bool> The form returns, each bool represents whether the feature exists widget W;
      Access to a specific feature flag bit 5bool highpriority = Features (w) [5= Features (w) [5];/ /(2) ...
      The Widget Object Processwidget (W, highpriority) is processed according to the value of the above flag bit, and//(3) Processwidget (w, highpriority_alt);//(4) ...

      The code above (1) (3) works fine, but (2) (4) There is undefined behavior, why?

      Because Std::vector<bool> holds a bool, operator[] does not return a reference to the element in the vector container when it acts on vector<bool> ([] The operation returns a reference to the element within the container that applies to other types, except that bool does not apply, but instead returns an object of type Std::vector<bool>::reference. Why does this type of object exist? Because the vector<bool> is represented by a compact form of the bool value, each bit represents a bool. This makes the [] operation difficult because the std::vector<t>,[] operation should return a t& object, but C + + prohibits the return of a reference to bit, which means that the bool&amp cannot be returned; Then you have to find a way to return an object to simulate the behavior of bool&. As a result, the Std::vector<bool>::reference object appears, which can be automatically converted from bool& to bool type where needed. So, in (1), the implicit automatic conversion is successful, and in (2), Auto automatically receives the type of the Std::vector<bool>::reference object, no conversion occurs, and the object actually points to a temporary std::vector The internal memory address of the <bool> object, and when the statement is executed, the temporary object is destroyed, and the address that auto saves is also the dangling address. In (4) It will start undefined behavior.
    • Agent Class Introduction
      • Std::vector<bool>::reference is an example of a proxy class that exists to simulate and enhance other types of behavior. For example, the smart pointer types in the standard library are also examples of proxy classes, which are responsible for managing the raw pointers to resources.
      • There are proxy classes that are visible to the user, such as std::shared_ptr,std::unique_ptr. Other proxy classes are not visible to the user, such as: Std::vector<bool>::reference and Std::bitset::reference.
      • The technology called expression templates used in some C + + libraries is also part of this category, which is designed to improve the efficiency of numerical calculation code. Example 2:
        = m1 + m2 + m3 + M4;

        If the operator+ operation returns a proxy class such as: Sum<matrix, matrix> instead of the result itself, which is the Matrix object, then this expression can be evaluated efficiently.

        Because the type of the object is encoded into the entire initialization expression, for example: Sum<sum<sum<matrix, Matrix>, Matrix>, matrix>.
    • General rules, the invisible proxy class does not apply to auto, because the proxy class object typically survives only one statement, so the variable that creates the proxy class object violates the basic library design assumptions.
  • When auto pushes out the proxy class type, it needs to do a static conversion of the proxy class type to the actual type for the expression, rather than discarding auto
    • For example 1 above:
      Auto highpriority = static_cast<bool> (Features (w) [5]);
    • For example 2 above:

      Auto sum = static_cast<matrix> (m1 + m2 + m3 + M4);
3. Summary

Auto Automatic type deduction can simplify the code, avoid the overhead of implicit conversion, increase program portability and reduce the complexity of refactoring, but also because of the conflict with the implicit proxy class, there are some potential problems, but these problems are not caused by auto, but the problem of the proxy class itself. Therefore, explicit static type conversions can preserve the advantages of auto, while guaranteeing the correctness of the program.

[Effective modern C + + (11&14)] Chapter 2:auto

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.