<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      《Effective Modern C++》翻譯--條款2: 理解auto自己主動類型推導

      條款2: 理解auto自己主動類型推導

      假設你已經讀過條款1關于模板類型推導的內容,那么你差點兒已經知道了關于auto類型推導的所有。

      至于為什么auto類型推導就是模板類型推導僅僅有一個地方感到好奇。那是什么呢?即模板類型推導包含了模板、函數和參數,而auto類型判斷不用與這些打交道。

      這當然是真的??墒菦]關系。

      模板類型推導和auto自己主動類型推導是直接匹配的。

      從字面上看,就是從一個算法轉換到還有一個算法而已。

      在條款1中。闡述模板類型推導採用的是常規的函數模板:

      template<typename T>
      void f(ParamType param);

      而且是常規方法進行調用:

      f(expr);    //call f with some expression

      在調用f的過程中。編譯器通過expr推導出T和ParamType的類型。

      當使用auto關鍵字聲明一個變量時。auto關鍵字就扮演者上述模板中T的角色,而且類型說明符與ParamType扮演者相同的角色。比語言描寫敘述更加清晰的是展示他們。所以請看這種樣例:

      auto x = 27;

      這樣,x的類型說明符與自己一樣。

      還有一方面,這樣聲明:

      const auto cx = x;

      這里的類型說明符是const auto。而這里:

      const auto& rx = x;

      此時類型說明符是const auto&。為了判斷上面這些樣例中的x,cx和rx變量,編譯器起到的作用就是為每一個聲明提供一個模板,而且使用對應的初始化表達式來調用這些模板:

      template<typename T>        //conceptual template for deducing x's type
      void func_for_x(T param);   
      
      func_for_x(27);             //conceptual call: param's deduced type is x's type
      
      template<typename T>        //conceptual template for deducing cx's type
      void func_for_cx(const T param);   
      
      func_for_cx(x);             //conceptual call: param's deduced type is cx's type
      
      template<typename T>        //conceptual template for deducing rx's type
      void func_for_rx(const T& param);   
      
      func_for_rx(x);             //conceptual call: param's deduced type is rx's type

      正如我之前所說,auto類型推導與模板類型推導是一樣的。

      條款1中依據ParamType和在常規模板中param的類型說明符,把模板類型推導分為三種情況。

      在通過auto進行變量類型推導時。類型說明符替代了ParamType,但也是分為三個情況:

      ?第一種情況:類型說明符是一個指針或是引用,但不是universal reference。

      ?另外一種情況:類型說明符是一個universal reference。

      ?第三種情況:類型說明符既不是指針也不是引用。

      我們分別看看第一和第三種情況的樣例:

      auto x = 27;           //case 3 (x is neither ptr nor reference)
      
      const auto cx = x;     //case 3 (cx isn't either)
      
      const auto& rx = x;    //case 1 (rx is non-universal ref.)

      另外一種情況正如你期待的那樣:

      auto&& uref1 = x;       //x is int and lvalue, so uref1's type is int&
      
      auto&& uref2 = cx;      //cx is const int and lvalue, so uref2's type is const int&
      
      auto&& uref3 = 27;      //27 is int and rvalue, so uref3's type is int&&

      條款1中總結了對于非引用類型的說明符,數組和函數名怎樣退化為指針。這當然相同適用于auto類型推導:

      const char name[] = "R. N. Briggs";  //name's type is const char[13]
      
      auto arr1 = name;                    //arr1's type is const char*
      
      auto& arr2 = name;                   //arr2's type is const char (&)[13]
      
      void someFunc(int, double);       //someFunc is a function; type is void(int, double)
      
      auto func1 = someFunc;              //func1's type is void(*)(int, double)
      
      auto& func2 = someFunc;             //func2's type is void(&)(int, double)

      正如您所見,auto類型推導真的和模板類型推導是一樣的。

      就好比一枚硬幣的兩個面相同。

      您肯定期待二者的不同。讓我從觀察聲明一個變量并初始化為27開始,在C++98中。給了你兩種語法選擇:

      int x1 = 27;
      int x2(27);

      C++11中還添加了這個:

      int x3 = {27};
      int x4{27};

      總之。四種語法都得到了一個結果。就是把變量初始化為27。

      可是正如條款5解釋的那樣。使用auto取代固定的類型來聲明變量有非常多的優勢,所以使用auto關鍵字取代上面程序中的int類型。簡單的文本替換我們就得到這種代碼:

      auto x1 = 27;
      auto x2(27);
      auto x3 = {27};
      auto x4{27};

      上面的這些都能夠通過編譯??墒桥c之前的相比,代表的含義已經不同了。上面四個表達式中前兩個實際上是聲明一個值為27int類型的變量。而后兩個,是聲明一個類型為std::initializer_list<int>,而且具有一個值為27的元素!

      auto x1 = 27;        //type is int, value is 27
      
      auto x2(27);         //同上
      
      auto x3 = {27};      //type is std::initializer_list<int>, value is {27}
      
      auto x4{27};         //同上

      這是由于auto類型推導有特俗的規則。當為auto聲明的類型進行初始化使用封閉的大括號時,則推導的類型為std::initializer_list。

      假設這種類型不能被推導。這種編碼是被編譯器拒絕的:

      auto x5 = {1, 2, 3.0}; //error! can't deduce T for std::initializer_list<T>

      正如上面凝視中提示的那樣,這種情況下類型推導會失敗。但更重要的是認清此時採用了兩種類型推導。一個是通過auto完畢對x5的類型推導。由于x5是使用大括號進行的初始化,所以x5必須被推導為std::initializer_list類型。可是std::initializer_list是一個模板。對于std::initializer_list<int>
      的實例化須要推導T的類型。

      這種類型推導發生另外一種類型推導的管轄范圍:模板類型推導。

      在這個樣例中,類型推導失敗,由于初始化值不具有單一類型。

      對待使用大括號進行初始化,auto類型推導和模板類型推導是有差別的。當一個auto變量被大括號進行初始化時,推導的類型為std::initializer_list實例化的類型。假設一個模板面臨著對于大括號初始化進行類型推導,這種代碼是被拒絕的。(條款32將解釋完美的轉發)

      你會懷疑為什么對于大括號進行初始化。auto類型推導會有特殊的規則呢,而模板類型推導則沒有。我自己對此也表示懷疑。不幸的是,我找不到令人信服的解釋。

      可是規則就是規則,這也就意味著對于auto推導用大括號初始化的變量時你必須銘記于心,推導類型的總是std::initializer_list。這是特別重要的是要牢記這一點,假設你面對在大括號包圍初始化值作為理所當然的初始化的理念。

      在C++11編程中。當中最典型的錯誤是你想聲明一個其它類型的變量,卻聲明一個std :: initializer_list變量。重申一下:

      auto x1 = 27;    //x1 and x2 are ints
      auto x2(27);
      
      auto x3 = {27};  //x3 and x4 are std::initializer_list<int>s
      auto x4{27};

      這個陷阱使得一些開發人員僅僅有迫不得已的時候才使用大括號初始化變量。(我們在條款7中再討論。)

      對于C++11來說。這里是所有的內容,可是對于C++14,故事還在繼續。C++14同意使用auto去推導函數的返回值(參見條款3)。而且C++14中的lambda表達式在參數聲明時能夠使用auto類型推導??墒?,這里使用的auto推導採用的是模板推導的規則,而不是auto類型推導的規則。

      這就意味著,使用大括號初始化將造成類型推導失敗。所以使用auto作為返回類型的函數返回一個使用大括號初始化的變量編譯不會通過:

      auto createInitList()
      {
          return {1, 2, 3}; //error: can't deduce type for {1, 2, 3}
      }

      相同的道理也適用于C++14中lambda表達式使用auto作為參數(因此產生一個通用lambda表達式):

      std::vector v;
      ....
      auto resetV = [&v](const auto& newValue) { v = newValue;};//C++14 only
      ....
      resetV({1, 2, 3});            //error! can't deduce type for {1, 2, 3}

      終于的結果是,假設不使用大括號進行初始化。auto類型推導是和模板類型推導一致的。僅在這種情況下(使用大括號進行初始化)。auto推導為一個std:: initializer_list,但模板類型推導會失敗。

      請記?。?/strong>

      ?auto類型對象通常與模板類型推導是相同的。

      ?唯一的例外是:使用auto和大括號進行初始化時,自己主動推導為std::initializer_lists。

      ?對于使用括號進行初始化,模板類型推導會失敗。

      posted @ 2017-08-20 18:45  lytwajue  閱讀(413)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲成A人片在线观看无码不卡| 99亚洲男女激情在线观看| 一本精品99久久精品77| 国产精品入口中文字幕| 香港特级三A毛片免费观看| 婷婷丁香五月六月综合激情啪| 宾馆人妻4P互换视频| 中文字幕人妻不卡精品| 成在线人免费视频| 夜夜高潮次次欢爽av女| 九九热在线这里只有精品| 亚洲国产高清在线观看视频 | 韩国 日本 亚洲 国产 不卡| 亚洲五月天综合| 国产成人高清在线重口视频| 高清中文字幕国产精品| 精品久久人人妻人人做精品 | 亚洲欧美中文字幕日韩一区二区| 十八禁午夜福利免费网站| 人妻教师痴汉电车波多野结衣| 欧美牲交a欧美牲交aⅴ图片| 京山县| 成人欧美一区二区三区在线观看 | 91精品91久久久久久| 起碰免费公开97在线视频| 天堂a无码a无线孕交| 成在人线av无码免费高潮水老板| 午夜精品国产自在| 亚洲精品成人A在线观看| 九九热精品在线观看| 青青国产揄拍视频| 甘孜县| 国产视频一区二区三区四区视频| 99RE8这里有精品热视频 | 久久精品免视看国产成人| 延安市| 久久久无码精品亚洲日韩蜜臀浪潮| 欧美怡春院一区二区三区| 宁津县| 国产在线无码不卡播放| 欧美性69式xxxx护士|