日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++20 - 下一个大版本功能确定

發布時間:2025/5/22 c/c++ 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++20 - 下一个大版本功能确定 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

C++20的功能特性已經于3月份凍結,顯然這次終于來了一波大的改進,而不再是像之前C++14/C++17那般小打小鬧的做小步快跑,尤其是三個討論很久的大feature終于被合入主干;并且這些feature終將會極大地影響后續C++代碼的書寫方式。

核心語言特性終于有了大變化

新的版本之所以被認為是下一個大的版本,主要原因還是來自于核心語言特性的擴充和簡化。看起來好像兩個目標有些互相矛盾,但是內在的邏輯其實還是統一的:

  • 擴充新的特性可以彌補之前一些遺留已久的功能限制,方便提高程序員的生產力,減少社區中長期存在的奇技淫巧侵蝕程序員寶貴的心智空間;
  • 簡化的方向主要是出于“照顧”新手程序員,幫助他們更快地上手產生生產力而不是匍匐在陡峭的學習曲線上靠長期的實踐積累來摸索,從而培養下一代的新鮮血液,否則語言就會因為失去活力而慢慢消亡;這顯然不是標準委員會愿意看到的。

從這兩個角度看,也許片面地評價標準委員會的資深專家們為“學院派”或者“老學究”,總歸是有些不合適的;因為C++一開始在90年代上半段的風靡完全是因為它是一門實用的程序語言。 只是隨著時間的推進,很多早期做出的設計決策多多少少被整個產業界的各色各樣的業務需求催生的奇技淫巧所侵蝕

尤其是模板元編程的流行和語言特性本身的滯后帶來的矛盾一直沒有得到合適的處理,背后的原因正是標準委員會需要照顧已有的軟件代碼的兼容性(當然背后也有很多大公司的利益考量),妥協再妥協;最終演變成不得不變的地步。

Concepts

像concept這樣可以明顯提升程序員生活質量的特性(想象一下用錯了一個容器的成員函數之后GCC打印出來的”成噸”的編譯錯誤,很多程序員形容是恨不得捏著鼻子繞著走),愣是從C++03定稿之后就被提出出來,卻活生生被推遲了一次又一次,甚至GCC的版本庫上的concepts分支都經歷了加上來又移除掉的曲折過程 - 速度和質量始終是一對很難權衡的矛盾。

幸好,經歷了十幾年的再三討論,concept這一模板元大殺器終于被投票送進了C++20標準的正式列表里。

關于Concepts最好的介紹當然是Bjarne自己的這篇Concepts: The Future of Generic Programming的文章, 另外一個比較好的描述來自于cppreference;簡單來說,它完成的事情就是用來描述泛型定義中,關于類型參數的約束和校驗; 出于零成本的考慮,我們需要做到這個校驗可以

  • 編譯期間完成檢查,對生成的實際代碼沒有影響(就像手寫的代碼一樣)
  • 具備定義良好的接口形式,可以方便地進行組合
  • 盡量地保持通用性

使用Concepts

通過使用concepts,傳統的模板元編程方面關于編譯錯誤的痛點可以得到極大改善,編譯器可以給出更加符合人類直覺的錯誤提示。 比如標準庫中的std::find算法的聲明如下:

template< class InputIt, class T > InputIt find( InputIt first, InputIt last, const T& value );

這里的兩個模板參數其實有更多額外的要求用傳統的語法是沒法表達的,第一個類型參數Input我們期望它是一個可遍歷的迭代器類型,并且其中的元素類型需要和T類型匹配,并且該類型能夠用來做相等比較。 這些約束條件在現有的語言標準中都是隱性的,一旦用錯,編譯器就會拿海量的錯誤信息來招呼你,因為編譯器背后會使用SFINAE這樣的語言特性來比較各種重載并給出一個常常的candidate列表,然后告訴你任何一個嘗試都沒有成功,所以失敗了。

Concepts相當于將這些要求用一種顯而易見的方式給出來,比如我們想表述一個在序列容器上查找的類似算法,可以用concepts來描述為

template <typename S, typename T> requires Sequence<S> && Equality_comparable<Value_type<S>, T> Iterator_of<S> find(S& seq, const T& value);//using alias template<typename X> using Value_type<X> = X::value_type; template<typename X> using Iterator_of<X> = X::iterator;

這時候如果使用不滿足條件的輸入參數,編譯器會直觀地告訴我們錯誤的具體原因

vector<string> vs; list<double> list; auto p0 = find(vs, "waldo"); //okay auto p1 = find(vs, 0.11); //error! - can't compare string and double auto p2 = find(list, 0.5); //okay auto p3 = find(list, "waldo"); //error! - can't compare double and string

顯然這里的例子有點啰嗦,出于節約鍵盤敲擊次數的考慮(Java太啰嗦了?原來的模板元函數的寫法也已經夠啰嗦的了!),可以進一步簡化這個寫法,將簡單的concepts約束直接嵌入到聲明的地方:

template <Sequence S, typename T> requires Equality_comparable<Value_type<S>, T> Iterator_of<S> find(S& seq, const T& value);

自定義concepts

對于上面的簡單的concepts,標準庫已經提供了一個開箱可用的封裝,不過出于學習目的自己動手做一個輪子也很簡單。比如用上面的比較為例,可以寫作

template <typename T> concept bool Equality_comparable = requires(T a, T b) {{ a == b} => bool; //compar with ==, and should return a bool{ a != b} => bool; //compare with !=, and should return a bool }

語法上和定義一個模板元函數很想象,所不同的地方是

  • 這里我們定義的對象是一個關于類型的檢查約束
  • 這里的requires部分引申出具體的檢查約束,必須同時實現操作符相等和不相等,兩個操作符都需要返回bool類型
  • 整個concept本身可以用在邏輯表達式中

簡化concept的格式負擔

如果能將簡單的事情變得更簡單,為什么不更進一步呢?這個設計哲學是C++的核心設計思想之一(參見Bjarne的D&E CPP),考慮下面的例子

template <typename Seq>requires Sortable<Seq> void sort(Seq& seq);

這里的Sortable表示某個可以被排序的容器類型;因為concept也是用于限制類型,而函數的參數也是用來限定類型,一個自然的想法就是逐步簡化它

//應用上述的簡化方式,concept描述放在模板參數聲明中 template <Sortable Seq> void sort(Seq& seq);

進一步地,去掉template部分的聲明會更加簡單,就像是一個普通的函數聲明,只不過參數類型是一個編譯器可以檢查的泛型類型

void sort(Sortable& s);

這樣一來,就和其它語言中的接口很類似了,沒錯就和Java的JDK中的泛型接口很相似了;只是底層的實現技術是完全不一樣的,Java由于根深蒂固的OO設計而不得不借助于類型擦除術;當然這個扯的稍微遠了一點。

auto類型的參數

其實C++14里面已經允許了auto作為函數參數的類型這一用法,顯然它和concept的簡化寫法完全不矛盾。

void func(auto x); // x實際上可以是任意類型! void func1(auto x, auto y); //x和y可以是任意的類型,可以不相同

在多個參數的情況下, 如果我們想限定兩個參數的類型必須總是一樣,有一種很簡單的機巧做到

constexpr concept bool Any = true; //任何類型都是Any void func(Any x, Any y); //x和y的類型必須相同,盡管他們可以是任意類型

標準庫中的預定義concepts

C++20的標準庫中預備了很多開箱即用的concepts,通過庫的方式提供,用戶只需要包含<concepts>庫即可。 詳細的列表可以參考concepts header;從大的分來來看,包括

  • 核心語言相關的concepts,比如判斷類型是否相同,是否是由繼承關系,是否可以賦值/拷貝/構造/析構/轉換等。
  • 比較相關的concepts,如Boolean用來判斷是否可以用在邏輯判斷上下文中,EquallyComparable和EquallyComparableWith聲明了==運算符是否表述等價關系;StrictTotallyOrdered/StrictTotallyOrderedWith聲明了比較運算符是否產生一個完全有序的結果
  • 關于對象的concepts,包括Movable,Copyable,分別聲明可移動和可拷貝(包含了可以swap),而Semiregular聲明對象是否可以被移動/拷貝/交換/默認構造;Regular則等價于Semiregular加上EquallyComparable
  • 關于函數調用的concepts,包含Invocable(聲明對應的類型可以想函數一樣調用并用給定的一系列參數來作為輸入參數),Predicate指定可調用的對象符合斷言約束并返回bool,Relation指定對應的可調用函數是一個二元函數;StrictWeakOrdering則表明對應的函數滿足弱排序(具體細節需要一些邏輯數學知識)
  • 用于range庫的對象交換要求
  • 應該可以預期后續的版本將會加入更多的支持。

    編譯器的支持情況

    GCC目前仍然是通過TS的方式來支持,編譯時候需要加上-fconcepts開關; Clang的全功能支持已經在將近一年前在redit上宣布完工,只是其官方的列表上依然沒有更新。 MSVC則于更早一點宣布了完整的concept支持,只是我們需要Visual Studio 2017 15.7版本。

    The MSVC compiler toolset in Visual Studio version 15.7 conforms with the C++ Standard!
    https://devblogs.microsoft.com/cppblog/announcing-msvc-conforms-to-the-c-standard/

    總體上看來,GCC的開發進度有些遲緩,clange的也不算很透明,只有MSVC比較領先。

    模塊化支持

    模塊支持被寫入新的語言核心,這一新的封裝方式甚至可以認為是C++誕生35年以來最大的一個新功能; 也是語言標準化以來,第一次通過修改核心語法允許程序員用一種全新的方式來描述帶命名的信息封裝邊界。

    信息封裝手法的更新

    傳統的封裝手段基本上都是采用如下的方式:

    • 將用戶自定義的結構或者類取一個名字
    • 將相關聯的細節都隱藏在這個名字的后面

    不管是變量聲明,函數定義,自定義的類,結構體,無一例外都滿足這個模式。即使是模板元編程方法,其實也是通過類型綁定的方法間接地使用上述的封裝手段。

    頭文件的不完美封裝

    除了上述的基本信息封裝單元,C++中屈指可數的封裝辦法就剩下了從古老的C語言繼承下來的頭文件包含的方式了。 在軟件規模還局限在數萬行代碼一下的時代,使用頭文件的方式一股腦將需要的東西都大包大攬在一個編譯單元中,然后使用諸如唯一定義規則的方法讓鏈接器在生成最終可執行代碼或者庫的時候做沖突檢測是一個簡單而優雅的方案。 因為對于它想解決的問題規模來說,這樣的解決方案就足夠了。

    然而隨著行業中軟件項目的復雜性與日俱增,越來越多的商業項目需要數百甚至上千的頭文件被包含在一個編譯單元中,這個時候既有的方式就越來越捉襟見肘

  • 編譯時間長成為了一個突出的痛點,以至于實際項目中出于減少編譯時間的考慮,聰明的工程師發明了如IWYU的頭文件檢測工具來緩解這一問題
  • 像pimp慣用法這樣的技術手段可以減少放在頭文件中的依賴,但是程序員卻不得不承擔額外內存申請的開銷(可能沒有這么個指針很多對象本身就可以在棧上完成快速構造和析構),即使有了unique_ptr來環境內存泄露的隱憂
  • 模板方式提供的抽象代碼無法聲明,必須放置在頭文件中內聯實現,否則對應的cpp文件在編譯單元進行代碼生成的時候會因為找不到定義而無法通過編譯;之前提出的一些export聲明也因為種種缺陷和編譯器支持不力而被廢棄
  • 簡單來看,現代的編程語言都或多或少帶有模塊化系統;缺乏現代的模塊化支持成為了C++語言的一種硬傷,嚴重制約了C++開發大項目的能力。

    模塊化系統需要的核心功能

    模塊化是一個很自然的邏輯信息隱藏手段,一個良好的模塊化系統應該允許

  • 良好的信息隔離,可以方便的指定哪些可以被外部訪問,哪些應該不允許被外部訪問
  • 支持嵌套的隔離機制,即可以在模塊中嵌套子模塊
  • 細粒度的訪問權限控制,尤其是能提供模塊內部/模塊外部/子模塊不同的訪問權限則更好
  • 操作系統的文件訪問系統保持一致的視圖,比如期望子文件夾可以對應子模塊是一個非常符合直覺的方法
  • 支持類似命名空間的隔離和訪問,比如支持重新導出一些模塊中公開的可訪問部分到另外一個空間中或者嵌套的命名、重命名模塊等
  • 構建系統、打包系統具有清晰易懂的交互接口;支持語言本身和IDE、語法檢查等生態系統工具設施的無縫融合
  • 要同時實現這些目標,并沒有想象中的容易;其它一些流行的編程語言其實都小心仔細地對這些可能“討好”程序員的目標做取舍,并在定義中詳細地描述好限制。 比如Java一開始用Jar打包的方式來模擬模塊,但是卻由于不支持嵌套子模塊中復雜的訪問控制而遭到很多用戶的不滿;而Go語言中的模塊和文件系統中文件名的糾葛同樣也是Go語言中一個晦澀的知識點。 NodeJS通過NPM機制來提供模塊化支持,然而其嵌套的打包方式和讓人窒息的依賴樹結構導致打包的時候需要依賴其它的第三方工具才能避免中招。

    后向兼容的艱難挑戰

    C++的模塊機制是奔著替換舊有的頭文件包含機制的目標來的,同時又因為需要照顧龐大的既有代碼庫不被破壞而不得不同時兼容頭文件包含機制。 和已有的其它語言特性一樣,這種向后兼容帶來的額外復雜性是否是必要的還又不小不同的聲音,不過主流的聲音還是決定走兼容的道路。

    基本語法

    如果我們希望聲明一個模塊,可以用如下的語法

    export module example; //聲明一個模塊名字為example export int add(int first, int second) { //可以導出的函數return first + second; }

    因為我們丟棄了頭文件的方法,可以將該模塊定義保存在example.cppm的文件中。這里的cppm后綴用于告訴編譯器這是一個模塊定義文件。

    假設我們希望使用該模塊,則用如下的代碼

    import example; //導入上述定義的模塊 int main() {add(1, 2); //調用example模塊中的函數 }

    分離模塊接口和實現

    如果我們想分離模塊的聲明和實現,將他們放在不同的文件中,這樣更符合傳統的接口定義和實現分離的編寫代碼方法(其實可以看作是C++比Java更干凈的一個地方),我們可以對上面的example.cppm做如下的修改

    export module example; extern int add(int first, int second);

    然后創建一個源代碼文件,放置模塊函數的實現

    module example; //當前模塊是example int add(int first, int second) {return first + second; }

    出于靈活起見,C++20支持將一個模塊中聲明的函數放在多個模塊實現單元中分別實現,這樣更容易實現干凈的代碼,并提高編譯速度。

    隔離權限指定

    模塊訪問權是通過export聲明來指定的,沒有聲明的類或者函數等默認是不能被外部代碼訪問的;基于聲明的語法也決定了如果分離聲明和實現,可見性在實現單元中其實是忽略的。

    為了避免代碼變得過于啰嗦,語法層面上也支持通過括號作用于一次性聲明多個導出函數或者類,比如

    export module example; export {void doSth();int doAnother(auto x, auto y); } void internalImpl(); //外部不可訪問

    模塊和namespace是正交的語言設施

    舊的C++標準早就支持通過namespace來實現信息封裝和隔離,而新的module機制可以和namespace結合使用,提供清晰的隔離結構,比如

    export module example; export namespace name {void doSth();int doAnother(auto x, auto y); }

    語言機制上提供了靈活的手段,但是程序員卻要自己做好權衡,保持模塊的粒度適中,匹配實際的應用場景。

    模塊重新導出

    實際應用中,復雜的軟件項目可能有很多形形色色的模塊,它們可能處于不同的抽象單元;和應用代碼比較近的上層模塊可能需要將某些它自己可見的模塊開放給上層代碼直接使用,提供重新導出的功能可以極大地提高信息封裝的能力,提高模塊的內聚度減少不必要的耦合。

    一個簡單的方法就是將import的部分重新放在export塊中,即下面的代碼例子

    export module mid; export {import low_module1;import low_module2;void myFunc(auto x); }

    標準庫中的模塊

    標準庫中提供的工具函數和類顯然應該被模塊化,只需要使用import std.xxx即可導入。 現代的WG21委員會的工作方式是有很多并行開發但是還沒有進入主干庫的”準標準庫”,編譯器可以選擇實現,等到對應的規范成熟的時候,它們才會被正式地移入標準庫中。

    Visual C++的封裝方式如下

  • std.filesystem提供文件系統的庫,相當于<experimental/filesystem>
  • std.memory 提供智能指針的庫,相當于<memory>
  • std.regex提供對正則表達式庫的封裝,相當于<regex>
  • std.threading提供對線程庫的支持(已經于C++11中正式支持),相當于<atomic>/<future>/<mutex>/<thread>/<shared_mutex>
  • std.core包含了其它所有的標準庫設施
  • 潛在的爭議?

    作為一門有著30多年歷史的語言,模塊化機制的一個設計難點就是保持和古老的include機制(本質上是代碼的復制)兼容該如何實現。 好在WG21經過漫長的討論終于實現了起碼在理論上完美的兼容 - 用戶可以自由混用兩者,只要不產生重復和鏈接問題即可。 Redit的cpp頻道里面有人發起了一個是否提供一種機制讓用戶強制在某一個模塊中清理舊有的include模式的討論,采用的思路正式類似Rust語言的版本指定的思路。

    這個想法其實有很重要的現實意義,因此有很多自身CPP用戶發表了自己的看法,大概標準定義成現在這個樣子應該主要是兩個方面的原因

  • 委員會中的代表有很多來自于大公司,這些公司有海量的遺留代碼;因此出于自身利益的考慮他們不會選擇一種不兼容的方案和自己過不去。
  • 社區分裂的風險,這個其實從C++03誕生依賴就有人開始質疑,乃至于早期的D語言就是沖著這一點不滿才決定選擇單干,可惜有評論認為現在的D語言的分裂情況和C++比較起來完全是不遑多讓的。
  • 這些問題其實都是很現實的問題,個人覺得WG21選擇向后兼容的思路并沒有什么問題,因為從新發明輪子的時候都是簡單的,真正復雜的是如何長期穩定地維護和更新。 C++的使用領域一直在縮小(或者有人說它是退回到了適合的領域)是個不爭的事實,然而在適合的領域,它的優勢不光在于語言本身還依賴于這些遺留系統的支撐。

    協程支持

    協程并不是一個新鮮的概念,甚至在現代編程語言出現之前很久就被提出出來,并在其它一些編程語言中被實現了很長時間了;它的基本思想是要求一個函數或者過程可以在執行過程中被操作系統或者調度器臨時中止,然后在適合的時機(獲取CPU計算資源等)再被恢復執行。詳細的描述可以參考這里。

    為什么需要協程

    協程最明顯的一個好處是允許我們書寫看起來順序執行但是其實背后卻異步執行的代碼,這樣技能協調人大腦擅長順序邏輯和計算機處理擅長異步執行的矛盾,兼顧效率和心智負擔。 同時協程還可以支持惰性賦值和初始化的邏輯,進一步提高程序的運行效率(僅僅在需要的時候做運算)但是又不對程序員的大腦產生太多的額外負擔。

    協程是一個比進程和線程更輕量級一點的概念,具體實現上來說可以分為有棧協程和無棧協程;技術上來說前者可以通過第三方庫實現就可以,但是性能開銷比較大也容易出問題;而無棧協程更加輕量級但是需要語言特性上做出改動

    C++20引入的協程屬于無棧協程。

    基本語法定義

    C++中的協程首先要是一個函數,它滿足如下特性

  • 可以被中止,保存狀態然后在合適的時機恢復執行 - 這也是協程的基本要求
  • 本身是不需要額外的棧的,即stackless
  • 當被暫時中止的時候,執行權被交回了調用者
  • 它的定義語法滿足下述的特征
  • 協程函數語法和關鍵字

    協程函數定義可以又如下一些特征:

    co_await操作符等待另外一個協程的完成

    比如如下的從網絡讀取數據并寫回對方的echo代碼,從邏輯上看循環內部的兩行代碼是順序執行的,但是co_awit關鍵字卻標明了邏輯上它是通過”等待“另外一個協程完成才繼續往下執行的。

    task<> tcp_echo_server() {char data[1024];for (;;) {size_t n = co_await socket.async_read_some(buffer(data));co_await async_write(socket, buffer(data, n));} }

    co_yield 可以直接掛起當前的協程執行并返回一個值

    比如下面的循環中,每次到yield操作的時候,當前的協程便被暫時中止執行并返回一個整數

    generator<int> iota(int n = 0) {while(true)co_yield n++; }

    這種用法在其它語言中也叫generator函數或者生成器。

    co_return用于直接返回

    lazy<int> f() {co_return 7; }

    返回類型要求

    因為協程的返回值并不是普通的值而是一個可以和另外一個協程相互協作的對象,因此C++標準對協程的返回值有如下要求:

    • 不能使用可變參數
    • 不能使用普通的return語句
    • 不能返回自動推導的類型,如auto或者concept類型等

    同時如下的函數也不能是協程

    • constexpr函數因為需要在編譯器運算,不能是協程
    • 構造函數和析構函數用于普通對象的構造,也不能被延遲執行進而不能是協程
    • 主函數不能是協程,否則操作系統無從啟動程序

    協程的執行

    任何一個協程其實由如下這些要素構成

  • promise對象需要充當一個橋梁,由協程內部改變其狀態,將值提交給另外一方等待該promise的協程
  • 外部協程操控另外一個協作協程的句柄,外部協程需要借助該句柄來決定是否掛起對方的協程或者將其協程幀銷毀
  • 隱式的協程狀態對象,該對象需要能夠
    • 保存內嵌的promise對象
    • 用值拷貝方法傳遞的參數值對象 - 顯然出于內存安全的考慮不能由引用或者指針
    • 當前執行到哪個階段的狀態標識,從而外部協程知道下一步是否應該遷移狀態還是需要銷毀幀數據
    • 其它一些生存期超越當前掛起點的局部變量
  • 協程執行的流程

    當一個協程執行的時候,它的實際運行順序如下

  • 使用operator new來分配上述的狀態對象
  • 拷貝所有的函數參數到這個對象中(因為協程本身也是個函數),值類型直接拷貝,如果由引用或者指針類型,其安全性需要程序員自己保證有效性,因為在協程中他們同樣使引用和指針
  • 構造promise對象,這里先查找它是否支持對應協程所有傳入參數為參數簽名的構造函數并調用,如果沒有則調用默認構造函數來構造
  • 調用promise.get_return_object函數,將結果放在一個局部變量中;這樣第一次協程被掛起的時候,該局部變量就可以被返回給調用者。如果在第一次執行到掛起之前發生了異常,對應的結果都不會放置在promise中,而是通過該局部變量返回
  • 調用promise.initial_suspsed函數,并使用co_await等待它的結果。通常情況下,promise類型要么返回suspend_always,要么返回suspend_never;前者對應的使延遲啟動的協程,后者則對應提前啟動的協程
  • 當co_await promise.initial_suspend恢復的時候,協程的函數體才開始別執行
  • 當該協程函數執行到一個掛起點,返回對象將會通過必要的類型轉換返回給外部協程的等待方。

    返回

    如果協程函數執行到一個co_return語句,則執行如下的操作

  • 如果返回類型是如下的幾種,則調用promise.return_void
    • co_return;
    • co_return expr; 但是expr的類型其實是void
    • 直接跳過了可能的co_return語句而執行到了函數的結果;如果promise對象恰好定義了Promise::return_void()函數,那么行為就是未定義的,需要格外留意!
  • 否則將調用promise.return_value(expr)返回需要的類型
  • 銷毀協程開始階段創建的所有的局部自由變量,銷毀的順序和構造順序相反
  • 調用promise.final_suspend函數,并等待其co_awit結果
  • 協程異常處理

    如果協程中拋出了未捕獲異常,它的行為如下

  • 捕獲異常,并調用promise.unhandled_exception函數
  • 調用promise.final_suspend函數,并等待其co_awit結果
  • 狀態對象的銷毀

    當協程狀態對象因為co_return或者異常情況需要銷毀的時候,其執行過程如下

  • 調用promise對象本身的析構函數
  • 調用協程參數對象的析構函數
  • 調用operator delete來完成對狀態對象本身的銷毀
  • 將執行權交回外部調用者
  • 堆內存分配

    協程的狀態必須要通過operator new來分配,因為標準要求這里必須是無棧協程。分配過程遵循如下兩條規則

  • 如果Promise類型定義了一個類級別的operator new,則優先選擇此分配方法,否則會調用全局的operator new來完成內存分配
  • 如果Promise類型定義了自定義的operator new,并且其函數簽名和協程的函數參數簽名一致,這些參數將會被一并傳遞給該函數,這樣的目的是為了和leading allocator convention的行為保持一致,即簽名一致的分配器有優先權
  • 可能的分配優化

    如果有辦法事先確認協程狀態對象的生存周期一定比調用方的生存周期短,并且該協程的幀大小在調用的時候可以明確得到。 該優化即使對用戶自定義的內存分配器也可以使用。 這種情況下,被調用的協程的棧幀其實是內嵌在了調用方的函數棧幀中,就像一個迷你的內聯函數調用一樣。

    Promise類型

    實際的promise類型則由編譯器根據實際協程聲明中的簽名類型結合std::corountine_traits模板推到得出。

    比如當一個協程的類型被定義為 task<float> foo(std::string x, bool flag),那么編譯器推導出來的類型為std::coroutine_traits<task<float>, std::string, bool>::promise_type。

    如果協程被定義為非static的成員函數,比如task<void> my_class::method1(int x) const,對應的推導出來的Promise類型為std::coroutine_traits<task<void>, const my_class&, int>::promise_type,同時對象類型會被放置在第一個參數模板了行中。

    編譯器支持情況

    Visual Studio是這個提案的主推者之一,所以早在2013年MSVC就提供了自己的協程實現;并且在VS2017中正式將關鍵字向標準提案靠攏。 Clang也提供了支持,盡管其C++ Status頁面顯示的還是partial支持。 遺憾的是GCC的corountine支持還處于比較早期的階段,目前仍然在一個分支上開發。

    原文:https://skyscribe.github.io/post/2019/06/23/cpp-20-modules-concepts-coroutine/

    《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

    總結

    以上是生活随笔為你收集整理的C++20 - 下一个大版本功能确定的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 日韩欧美高清一区 | 国产精品久久不卡 | 国产精品免费av一区二区三区 | 9.1成人看片免费版 日韩经典在线 | 欧美影院在线观看 | 2019国产精品 | 欧美夫妻性生活视频 | 欧美性生交大片免费看app麻豆 | 久久久青青草 | 国产毛片在线看 | 欧美精品亚洲一区 | 国产91综合 | 精品久久久久久亚洲精品 | 小俊大肉大捧一进一出好爽 | 精品三级 | 久久人成| 亚洲天堂日本 | 亚洲国产成人精品久久久 | 久久福利一区 | 中文字幕一级片 | 日本在线不卡一区二区 | 中文字幕一区二区人妻痴汉电车 | 欧美日韩在线视频一区二区三区 | 国产精品视频在线看 | 国产一区亚洲二区 | 国产色无码精品视频国产 | 久久久无码人妻精品无码 | 天天免费视频 | 亚洲图片 自拍偷拍 | 亚洲欧美国产毛片在线 | 午夜亚洲福利在线老司机 | 欧日韩不卡在线视频 | 国产女上位 | 亚洲视频自拍偷拍 | 99视频在线精品免费观看2 | 综合精品一区 | 熟女熟妇伦久久影院毛片一区二区 | 国产在线1| 青青操91 | 毛片在线免费视频 | 欧美在线一级 | 亚洲欧美日韩一区在线观看 | 亚洲欧美一区二区三区四区 | 亚洲乱码国产乱码精品 | 日韩在线观看第一页 | 一区二区三区免费在线视频 | 老汉av在线 | 日韩狠狠操 | 久热色| 国产成人精品一区二区三区四区 | 一区二区免费在线观看 | 亚洲综合小说 | 成人av一区二区三区在线观看 | 樱井莉亚av| 午夜视频一区 | 亚洲天堂网在线观看 | 漂亮人妻被黑人久久精品 | 日韩高清片 | 人妻少妇精品无码专区二区 | 男人桶进美女尿囗 | 91天天看 | 日本不卡视频一区 | 动漫裸体无遮挡 | 国内成人自拍视频 | 国产激情视频一区二区三区 | 亚欧洲精品在线视频免费观看 | 欧美孕妇性xx | 国产精品入口a级 | 欧美成人综合网站 | 黑人一级黄色片 | 免费av手机在线观看 | 久久午夜国产 | 天堂无乱码 | 久久婷婷激情 | 久久久久久久黄色 | 色综合图片区 | 成人午夜视频免费在线观看 | 国产一伦一伦一伦 | 污网站在线免费 | 女同av在线| 免费无码肉片在线观看 | 合欢视频在线观看 | 超碰夜夜 | 国产精品91在线观看 | 欧美日韩国产色 | 午夜爱| 色牛av| 悟空影视大全免费高清观看在线 | 国产精品久久久久久69 | 超碰在线香蕉 | 理论av| 超碰在线观看免费版 | 亚洲成人免费视频 | www.波多野结衣.com | 亚洲国产精品18久久久久久 | av不卡在线 | 99热这里只有精品9 日韩综合在线 | 国产精品扒开腿做爽爽爽a片唱戏 | 国模少妇一区二区 |