青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

專職C++

不能停止的腳步

  C++博客 :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
  163 Posts :: 7 Stories :: 135 Comments :: 0 Trackbacks

常用鏈接

留言簿(28)

我參與的團(tuán)隊(duì)

搜索

  •  

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

原文:http://geek.csdn.net/news/detail/228484

C++17標(biāo)準(zhǔn)在2017上半年已經(jīng)討論確定,正在形成ISO標(biāo)準(zhǔn)文檔,今年晚些時(shí)候會(huì)正式發(fā)布。本文將介紹最新標(biāo)準(zhǔn)中值得開發(fā)者關(guān)注的新特新和基本用法。

總的來(lái)說(shuō)C++17相比C++11的新特性來(lái)說(shuō)新特性不算多,做了一些小幅改進(jìn)。C++17增加了數(shù)十項(xiàng)新特性,值得關(guān)注的特性大概有下面這些:

  • constexpr if
  • constexpr lambda
  • fold expression
  • void_t
  • structured binding
  • std::apply, std::invoke
  • string_view
  • parallel STL
  • inline variable

剩下的有一些來(lái)自于boost庫(kù),比如variant,any、optional和filesystem等特性,string_view其實(shí)在boost里也有。還有一些是語(yǔ)法糖,比如if init、deduction guide、guaranteed copy Elision、template、nested namespace、single param static_assert等特性。我接下來(lái)會(huì)介紹C++17主要的一些特性,介紹它們的基本用法和作用,讓讀者對(duì)C++17的新特性有一個(gè)基本的了解。

fold expression

C++11增加了一個(gè)新特性可變模版參數(shù)(variadic template),它可以接受任意個(gè)模版參數(shù)在參數(shù)包中,參數(shù)包是三個(gè)點(diǎn)…,它不能直接展開,需要通過(guò)一些特殊的方法才能展開,導(dǎo)致在使用的時(shí)候有點(diǎn)難度。現(xiàn)在C++17解決了這個(gè)問(wèn)題,讓參數(shù)包的展開變得容易了,F(xiàn)old expression就是方便展開參數(shù)包的。

fold expression的語(yǔ)義 
fold expression有4種語(yǔ)義:

  1. unary right fold (pack op …)
  2. unary left fold (… op pack)
  3. binary right fold (pack op … op init)
  4. binary left fold (init op … op pack)

其中pack代表變參,比如args,op代表操作符,fold expression支持32種操作符:

+ - * / % ^ & | = < > << >> += -= *= /= %= ^= &= |= <<= >>= == != <= >= && || , .* ->*

unary right fold的含義

fold (E op …) 意味著 E1 op (… op (EN-1 op EN)).

顧名思義,從右邊開始fold,看它是left fold還是right fold我們可以根據(jù)參數(shù)包…所在的位置來(lái)判斷,當(dāng)參數(shù)包…在操作符右邊的時(shí)候就是right fold,在左邊的時(shí)候就是left fold。我們來(lái)看一個(gè)具體的例子:

template<typename... Args> auto add_val(Args&&... args) {     return (args +  ...); }  auto t = add_val(1,2,3,4); //10 

right fold的過(guò)程是這樣的:(1+(2+(3+4))),從右邊開始fold。

unary left fold的含義

fold (… op E) 意味著 ((E1 op E2) op …) op EN。

對(duì)于+這種滿足交換律的操作符來(lái)說(shuō)left fold和right fold是一樣的,比如上面的例子你也可以寫成left fold。

template<typename... Args> auto add_val(Args&&... args) {     return (... + args); }  auto t = add_val(1,2,3,4); //10 

對(duì)于不滿足交換律的操作符來(lái)說(shuō)就要注意了,比如減法。

template<typename... Args> auto sub_val_right(Args&&... args) {     return (args - ...); }   template<typename... Args> auto sub_val_left(Args&&... args) {     return (... - args); }  auto t = sub_val_right(2,3,4); //(2-(3-4)) = 3 auto t1 = sub_val_left(2,3,4); //((2-3)-4) = -5 

這次right fold和left fold的結(jié)果就不一樣。

binary fold的含義

Binary right fold (E op … op I) 意味著 E1 op (… op (EN-1 op (EN op I)))。

Binary left fold (I op … op E) 意味著 (((I op E1) op E2) op …) op E2。

其中E代表變參,比如args,op代表操作符,I代表一個(gè)初始變量。

二元fold的語(yǔ)義和一元fold的語(yǔ)義是相同的,看一個(gè)二元操作符的例子:

template<typename... Args> auto sub_one_left(Args&&... args) {     return (1 - ... - args); }  template<typename... Args> auto sub_one_right(Args&&... args) {     return (args - ... - 1); }  auto t = sub_one_left(2,3,4);// (((1-2)-3)-4) = -8 auto t1 = sub_one_right(2,3,4);//(2-(3-(4-1))) = 2 

相信通過(guò)這個(gè)例子大家應(yīng)該對(duì)C++17的fold expression有了基本的了解。

comma fold

在C++17之前,我們經(jīng)常使用逗號(hào)表達(dá)式和std::initializer_list來(lái)將變參一個(gè)個(gè)傳入一個(gè)函數(shù)。比如像下面這個(gè)例子:

template<typename T> void print_arg(T t) {     std::cout << t << std::endl; }  template<typename... Args> void print2(Args... args) {     //int a[] = { (printarg(args), 0)... };     std::initializer_list<int>{(print_arg(args), 0)...}; } 

這種寫法比較繁瑣,用fold expression就會(huì)變得很簡(jiǎn)單了。

template<typename... Args> void print3(Args... args) {     (print_arg(args), ...); } 

這是right fold,你也可以寫成left fold,對(duì)于comma來(lái)說(shuō)兩種寫法是一樣的,參數(shù)都是從左至右傳入print_arg函數(shù)。

template<typename... Args> void print3(Args... args) {     (..., print_arg(args)); } 

你也可以通過(guò)binary fold這樣寫:

template<typename ...Args> void printer(Args&&... args) {     (std::cout << ... << args) << '\n'; } 

也許你會(huì)覺(jué)得能寫成這樣:

template<typename ...Args> void printer(Args&&... args) {     (std::cout << args << ...) << '\n'; } 

但這樣寫是不合法的,根據(jù)binary fold的語(yǔ)法,參數(shù)包…必須在操作符中間,因此上面的這種寫法不符合語(yǔ)法要求。

借助comma fold我們可以簡(jiǎn)化代碼,假如我們希望實(shí)現(xiàn)tuple的for_each算法,像這樣:

for_each(std::make_tuple(2.5, 10, 'a'),[](auto e) { std::cout << e<< '\n'; }); 

這個(gè)for_each將會(huì)遍歷tuple的元素并打印出來(lái)。在C++17之前我們?nèi)绻獙?shí)現(xiàn)這個(gè)算法的話,需要借助逗號(hào)表達(dá)式和std::initializer_list來(lái)實(shí)現(xiàn),類似于這樣:

template <typename... Args, typename Func, std::size_t... Idx> void for_each(const std::tuple& t, Func&& f, std::index_sequence<Idx...>) {     (void)std::initializer_list<int> { (f(std::get<Idx>(t)), void(), 0)...}; } 

這樣寫比較繁瑣不直觀,現(xiàn)在借助fold expression我們可以簡(jiǎn)化代碼了。

template <typename... Args, typename Func, std::size_t... Idx> void for_each(const std::tuple<Args...>& t, Func&& f, std::index_sequence<Idx...>) {     (f(std::get<Idx>(t)), ...); } 

借助coma fold我們可以寫很簡(jiǎn)潔的代碼了。

constexpr if

constexpr標(biāo)記一個(gè)表達(dá)式或一個(gè)函數(shù)的返回結(jié)果是編譯期常量,它保證函數(shù)會(huì)在編譯期執(zhí)行。相比模版來(lái)說(shuō),實(shí)現(xiàn)編譯期循環(huán)或遞歸,C++17中的constexpr if會(huì)讓代碼變得更簡(jiǎn)潔易懂。比如實(shí)現(xiàn)一個(gè)編譯期整數(shù)加法:

template<int N> constexpr int sum() {     return N; }  template <int N, int N2, int... Ns> constexpr int sum() {     return N + sum<N2, Ns...>(); } 

C++17之前你可能需要像上面這樣寫,但是現(xiàn)在你可以寫更簡(jiǎn)潔的代碼了。

template <int N, int... Ns> constexpr auto sum17() {     if constexpr (sizeof...(Ns) == 0)         return N;     else         return N + sum17<Ns...>(); } 

當(dāng)然,你也可以用C++17的fold expression:

template<typename ...Args> constexpr int sum(Args... args) {     return (0 + ... + args); } 

constexpr還可以用來(lái)消除enable_if了,對(duì)于討厭寫一長(zhǎng)串enable_if的人來(lái)說(shuō)會(huì)非常開心。比如我需要根據(jù)類型來(lái)選擇函數(shù)的時(shí)候:

template<typename T> std::enable_if_t<std::is_integral<T>::value, std::string> to_str(T t) {     return std::to_string(t); }  template<typename T> std::enable_if_t<!std::is_integral<T>::value, std::string> to_str(T t) {     return t; } 

經(jīng)常不得不分開幾個(gè)函數(shù)來(lái)寫,還需要寫長(zhǎng)長(zhǎng)的enable_if,比較繁瑣,通過(guò)if constexpr可以消除enable_if了。

template<typename T> auto to_str17(T t) {     if constexpr(std::is_integral<T>::value)         return std::to_string(t);     else         return t; } 

constexpr if讓C++的模版具備if-else if-else功能了,是不是很酷,C++程序員的好日子來(lái)了。

不過(guò)需要注意的是下面這種寫法是有問(wèn)題的。

template<typename T> auto to_str17(T t) {     if constexpr(std::is_integral<T>::value)         return std::to_string(t);          return t; } 

這個(gè)代碼把else去掉了,當(dāng)輸入如果是非數(shù)字類型時(shí)代碼可以編譯過(guò),以為if constexpr在模版實(shí)例化的時(shí)候會(huì)丟棄不滿足條件的部分,因此函數(shù)體中的前兩行代碼將失效,只有最后一句有效。當(dāng)輸入的為數(shù)字的時(shí)候就會(huì)產(chǎn)生編譯錯(cuò)誤了,因?yàn)閕f constexpr滿足條件了,這時(shí)候就會(huì)有兩個(gè)return了,就會(huì)導(dǎo)致編譯錯(cuò)誤。

constexpr if還可以用來(lái)替換#ifdef宏,看下面的例子

enum class OS { Linux, Mac, Windows };  //Translate the macros to C++ at a single point in the application #ifdef __linux__ constexpr OS the_os = OS::Linux; #elif __APPLE__ constexpr OS the_os = OS::Mac; #elif __WIN32 constexpr OS the_os = OS::Windows; #endif  void do_something() {      //do something general       if constexpr (the_os == OS::Linux) {          //do something Linuxy      }      else if constexpr (the_os == OS::Mac) {          //do something Appley      }      else if constexpr (the_os == OS::Windows) {          //do something Windowsy      }       //do something general } //備注:這個(gè)例子摘自https://blog.tartanllama.xyz/c++/2016/12/12/if-constexpr/ 

代碼變得更清爽了,再也不需要像以前一樣寫#ifdef那樣難看的代碼塊了。

constexpr lambda

constexpr lambda其實(shí)很簡(jiǎn)單,它的意思就是可以在constexpr 函數(shù)中用lambda表達(dá)式了,這在C++17之前是不允許的。這樣使用constexpr函數(shù)和普通函數(shù)沒(méi)多大區(qū)別了,使用起來(lái)非常舒服。下面是constexpr lambda的例子:

template <typename I> constexpr auto func(I i) {   //use a lambda in constexpr context   return [i](auto j){ return i + j; };  } 

constexpr if和constexpr lambda是C++17提供的非常棒的特性,enjoy it.

string_view

string_view的基本用法

C++17中的string_view是一個(gè)char數(shù)據(jù)的視圖或者說(shuō)引用,它并不擁有該數(shù)據(jù),是為了避免拷貝,因此使用string_view可以用來(lái)做性能優(yōu)化。你應(yīng)該用string_view來(lái)代替const char和const string了。string_view的方法和string類似,用法很簡(jiǎn)單:

const char* data = "test"; std::string_view str1(data, 4); std::cout<<str1.length()<<'\n'; //4 if(data==str1)     std::cout<<"ok"<<'\n';  const std::string str2 = "test"; std::string_view str3(str2, str2.size()); 

構(gòu)造string_view的時(shí)候用char*和長(zhǎng)度來(lái)構(gòu)造,這個(gè)長(zhǎng)度可以自由確定,它表示string_view希望引用的字符串的長(zhǎng)度。因?yàn)樗皇且闷渌址运粫?huì)分配內(nèi)存,不會(huì)像string那樣容易產(chǎn)生臨時(shí)變量。我們通過(guò)一個(gè)測(cè)試程序來(lái)看看string_view如何來(lái)幫我們優(yōu)化性能的。

using namespace std::literals;  constexpr auto s = "it is a test"sv; auto str = "it is a test"s;  constexpr int LEN = 1000000; boost::timer t; for (int i = 0; i < LEN; ++i) {     constexpr auto s1 = s.substr(3); } std::cout<<t.elapsed()<<'\n'; t.restart(); for (int i = 0; i < LEN; ++i) {     auto s2 = str.substr(3); } std::cout<<t.elapsed()<<'\n';  //output 0.004197 0.231505 

我們可以通過(guò)字面量””sv來(lái)初始化string_view。string_view的substr和string的substr相比,快了50多倍,根本原因是它不會(huì)分配內(nèi)存。

string_view的生命周期

由于string_vew并不擁有鎖引用的字符串,所以它也不會(huì)去關(guān)注被引用字符串的生命周期,用戶在使用的時(shí)候需要注意,不要將一個(gè)臨時(shí)變量給一個(gè)string_view,那樣會(huì)導(dǎo)致string_view引用的內(nèi)容也失效。

std::string_view str_v; {     std::string temp = "test";     str_v = {temp}; } 

這樣的代碼是有問(wèn)題的,因?yàn)槌隽俗饔糜蛑螅瑂tring_view引用的內(nèi)容已經(jīng)失效了。

總結(jié)

本文介紹了C++17的fold expression、constexpr if、constexpr lambda和string_view。fold expression為了簡(jiǎn)化可變模板參數(shù)的展開,讓可以模板參數(shù)的使用變得更簡(jiǎn)單直觀;constexpr if讓模板具備if-else功能,非常強(qiáng)大。它也避免了寫冗長(zhǎng)的enable_if代碼,讓代碼變得簡(jiǎn)潔易懂了;string_view則是用來(lái)做性能優(yōu)化的,應(yīng)該用它來(lái)代替const char*和const string。

這些特性對(duì)之前的C++14和C++11做了改進(jìn)和增強(qiáng),非常酷,歡迎訂閱《程序員》,后續(xù)系列文章會(huì)接著介紹其他C++17中值得關(guān)注的新特性。

posted on 2017-07-28 13:25 冬瓜 閱讀(1909) 評(píng)論(1)  編輯 收藏 引用 所屬分類: 轉(zhuǎn)貼

Feedback

# re: [轉(zhuǎn)貼]C++17中那些值得關(guān)注的特性(上) 2017-07-31 17:44 Chipset
一堆學(xué)術(shù)派閑的蛋疼總搞語(yǔ)法,沒(méi)有一點(diǎn)實(shí)用價(jià)值。
就不能加點(diǎn)庫(kù)嗎?文件系統(tǒng),通信,圖形...  回復(fù)  更多評(píng)論
  

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美午夜免费影院| 亚洲欧美成人综合| 欧美成人午夜免费视在线看片| 国产一区二区三区最好精华液| 香蕉乱码成人久久天堂爱免费| 亚洲美女av电影| 欧美日本韩国在线| 亚洲欧美一区在线| 久久国产精彩视频| 亚洲国产激情| 亚洲久久一区二区| 国产免费亚洲高清| 欧美.www| 欧美日精品一区视频| 欧美一级淫片aaaaaaa视频| 新片速递亚洲合集欧美合集| 在线播放精品| 亚洲美女视频网| 欧美午夜大胆人体| 香蕉亚洲视频| 久久一区中文字幕| 亚洲午夜黄色| 欧美一级在线视频| 亚洲另类在线视频| 欧美一区二区三区免费视| 亚洲国产精品va在线看黑人动漫| 亚洲国产一区二区三区高清| 欧美视频观看一区| 理论片一区二区在线| 欧美日韩福利| 欧美精品日日鲁夜夜添| 欧美在线视频一区| 伊人成人网在线看| 一本色道久久综合一区| 黄色精品网站| 在线亚洲成人| 亚洲国产高清一区| 午夜伦欧美伦电影理论片| 亚洲精品久久久久中文字幕欢迎你| 99在线热播精品免费99热| 精品成人一区二区三区| 一区二区三区波多野结衣在线观看| 国产性色一区二区| 一区二区三区国产精品| 亚洲黄色大片| 久久国产精品高清| 羞羞视频在线观看欧美| 欧美日韩小视频| 欧美国产一区二区在线观看| 国产精品一区久久久| 亚洲日本欧美在线| 91久久久久久| 久久不射2019中文字幕| 性欧美1819sex性高清| 欧美日韩一级大片网址| 亚洲国产91| 在线成人性视频| 欧美在线精品一区| 久久疯狂做爰流白浆xx| 国产精品theporn| 99天天综合性| 国产精品99久久久久久宅男| 欧美成人在线免费观看| 欧美大片免费| 在线日韩精品视频| 久久久久国产精品一区| 久久久综合激的五月天| 国产亚洲欧美一区| 亚欧成人精品| 久久国产精品亚洲77777| 国产婷婷97碰碰久久人人蜜臀| 亚洲欧美日韩精品久久奇米色影视| 亚洲综合三区| 国产视频丨精品|在线观看| 午夜精品在线视频| 久久久精品一区| 在线看成人片| 欧美成人午夜剧场免费观看| 亚洲精品免费网站| 亚洲一区二区三区成人在线视频精品| 欧美日韩免费在线观看| 亚洲图片激情小说| 久久久成人精品| 怡红院av一区二区三区| 欧美成人三级在线| 夜夜嗨一区二区三区| 欧美一级播放| 精东粉嫩av免费一区二区三区| 久久视频国产精品免费视频在线| 亚洲电影毛片| 亚洲欧美成aⅴ人在线观看| 国产美女搞久久| 久热国产精品| 亚洲伦伦在线| 久久久久久999| 99视频在线观看一区三区| 欧美色视频日本高清在线观看| 亚洲欧美日韩天堂| 亚洲丁香婷深爱综合| 午夜精品一区二区三区四区| 久久高清一区| 久久九九热免费视频| 91久久线看在观草草青青| 国产精品劲爆视频| 久久久www成人免费无遮挡大片| 亚洲人成毛片在线播放| 久久精品国产亚洲a| 亚洲毛片一区二区| 国模精品娜娜一二三区| 欧美日本韩国一区二区三区| 久久精品一区二区三区四区| 亚洲九九爱视频| 欧美激情aⅴ一区二区三区 | 久久精品99国产精品日本| 亚洲激精日韩激精欧美精品| 欧美主播一区二区三区美女 久久精品人| 亚洲电影中文字幕| 国产精品中文字幕在线观看| 蜜桃av综合| 亚洲无线视频| 免费成人小视频| 欧美专区在线观看| 日韩性生活视频| 国产在线视频不卡二| 欧美精品一线| 亚洲欧美综合| 亚洲日本久久| 免费在线观看精品| 欧美一区=区| 国语自产精品视频在线看一大j8 | 欧美在线一二三四区| 在线亚洲伦理| 亚洲高清不卡在线| 国产欧美亚洲视频| 欧美私人啪啪vps| 亚洲综合精品四区| 中文久久乱码一区二区| 欧美国产免费| 久久在线视频在线| 午夜精品久久久久久久蜜桃app | 久久男人av资源网站| 亚洲欧美在线免费| 一本色道久久综合亚洲精品小说| 女女同性女同一区二区三区91| 久久久欧美精品| 欧美中文字幕在线| 亚洲天堂第二页| 亚洲精品三级| 亚洲人体偷拍| 999在线观看精品免费不卡网站| 黄页网站一区| 狠狠色综合网站久久久久久久| 国产精品视频导航| 欧美日本一区二区视频在线观看 | 亚洲第一偷拍| 亚洲欧洲美洲综合色网| 一本色道久久综合亚洲二区三区| 91久久午夜| 亚洲国内在线| 亚洲狠狠丁香婷婷综合久久久| 久久久www成人免费无遮挡大片| 久久精品99国产精品日本| 欧美有码视频| 久久精品国产欧美激情| 久久久777| 久久精品国产综合精品| 女人色偷偷aa久久天堂| 欧美粗暴jizz性欧美20| 亚洲高清自拍| 午夜久久影院| 亚洲精品一区二区三区不| 亚洲激情小视频| av成人免费观看| 尤物九九久久国产精品的分类| 亚洲精品久久久久| 亚洲永久免费| 欧美在线播放| 蜜臀a∨国产成人精品| 日韩视频中午一区| 亚洲一区二区免费在线| 欧美一区二区三区精品电影| 久久久免费精品视频| 欧美成人福利视频| 欧美区二区三区| 国产精品美女久久久| 黄色一区二区三区四区| 一本久道久久久| 欧美一区二区三区四区在线观看地址 | 亚洲激情视频网站| 亚洲午夜免费视频| 欧美一区二区精品在线| 女女同性精品视频| 国产亚洲精品成人av久久ww| 亚洲国产精品一区二区www在线| 亚洲日本在线观看| 小处雏高清一区二区三区| 欧美在线免费观看视频| 日韩午夜黄色| 久久久久一本一区二区青青蜜月| 欧美日本中文字幕|