在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

聊聊結構化綁定

CPP開發者 ? 來源:高性能架構探索 ? 2023-08-03 15:34 ? 次閱讀
動機

std::mapinsert方法返回std::pair,兩個元素分別是指向所插入鍵值對的迭代器與指示是否新插入元素的布爾值,而std::map::iterator解引用又得到鍵值對std::pair。在一個涉及std::map算法中,有可能出現大量的firstsecond,讓人不知所措。

#include
#include

intmain()
{
typedefstd::mapMap;
Mapmap;
std::pairresult=map.insert(Map::value_type(1,2));
if(result.second)
std::cout<first<second<

C++11標準庫添加了std::tie,用若干引用構造出一個std::tuple,對它賦以std::tuple對象可以給其中的引用一一賦值(二元std::tuple可以由std::pair構造或賦值)。std::ignore是一個占位符,所在位置的賦值被忽略。

#include
#include
#include

intmain()
{
std::mapmap;
boolinserted;
std::ignore,inserted)=map.insert({1,2});
if(inserted)
std::cout<

但是這種方法仍遠不完美,因為:

?變量必須事先單獨聲明,其類型都需顯式表示,無法自動推導;?對于默認構造函數執行零初始化的類型,零初始化的過程是多余的;?也許根本沒有可用的默認構造函數,如std::ofstream

為此,C++17引入了結構化綁定(structured binding)。

#include
#include

intmain()
{
std::mapmap;
auto&&[iter,inserted]=map.insert({1,2});
if(inserted)
std::cout<

結構化綁定這一語言特性在提議的階段曾被稱為分解聲明(decomposition declaration),后來又被改回結構化綁定。這個名字想強調的是,結構化綁定的意義重在綁定而非聲明。

語法

結構化綁定有三種語法:

attr(optional)cv-autoref-operator(optional)[identifier-list]=expression;
attr(optional)cv-autoref-operator(optional)[identifier-list]{expression};
attr(optional)cv-autoref-operator(optional)[identifier-list](expression);

其中,attr(optional)為可選的attributescv-auto為可能有constvolatile修飾的autoref-operator(optional)為可選的&&&identifier-list為逗號分隔的標識符,expression為單個表達式。

另外再定義initializer= expression{ expression }( expression ),換言之上面三種語法有統一的形式attr(optional) cv-auto ref-operator(optional) [ identifier-list ] initializer;

整個語句是一個結構化綁定聲明,標識符也稱為結構化綁定(structured bindings),不過兩處“binding”的詞性不同。

順帶一提,C++20中volatile的許多用法都被廢棄了。

行為

結構化綁定有三類行為,與上面的三種語法之間沒有對應關系。

第一種情況,expression是數組,identifier-list的長度必須與數組長度相等。

第二種情況,對于expression的類型Estd::tuple_size是一個完整類型,則稱E為類元組(tuple-like)類型。在STL中,std::arraystd::pairstd::tuple都是這樣的類型。此時,identifier-list的長度必須與std::tuple_size::value相等,每個標識符的類型都通過std::tuple_element推導出(具體見后文),用成員get()get(e)初始化。顯然,這些標準庫設施是與語言核心綁定的。

第三種情況,E是非union類類型,綁定非靜態數據成員。所有非靜態數據成員都必須是public訪問屬性,全部在E中,或全部在E的一個基類中(即不能分散在多個類中)。identifier-list按照類中非靜態數據成員的聲明順序綁定,數量相等。

應用

結構化綁定擅長處理純數據類型,包括自定義類型與std::tuple等,給實例的每一個字段分配一個變量名:

#include

structPoint
{
doublex,y;
};

Pointmidpoint(constPoint&p1,constPoint&p2)
{
return{(p1.x+p2.x)/2,(p1.y+p2.y)/2};
}

intmain()
{
Pointp1{1,2};
Pointp2{3,4};
auto[x,y]=midpoint(p1,p2);
std::cout<

配合其他語法糖,現代C++代碼可以很優雅:

#include
#include

intmain()
{
std::mapmap;
if(auto&&[iter,inserted]=map.insert({1,2});inserted)
std::cout<

利用結構化綁定在類元組類型上的行為,我們可以改變數據類型的結構化綁定細節,包括類型轉換、是否拷貝等:

#include
#include
#include

classTranscript{/*...*/};

classStudent
{
public:
constchar*name;
Transcriptscore;
std::stringgetName()const{returnname;}
constTranscript&getScore()const{returnscore;}
template
decltype(auto)get()const
{
ifconstexpr(I==0)
returngetName();
elseifconstexpr(I==1)
returngetScore();
else
static_assert(I
structtuple_size
:std::integral_constant{};

template<>
structtuple_element<0,?Student>{usingtype=decltype(std::declval().getName());};

template<>
structtuple_element<1,?Student>{usingtype=decltype(std::declval().getScore());};
}

intmain()
{
std::cout<

Student是一個數據類型,有兩個字段namescorename是一個C風格字符串,它大概是從C代碼繼承來的,我希望客戶能用上C++風格的std::stringscore屬于Transcript類型,表示學生的成績單,這個結構比較大,我希望能傳遞const引用以避免不必要的拷貝。為此,我寫明了三要素:std::tuple_sizestd::tuple_elementget。這種機制給了結構化綁定很強的靈活性。

細節

#include
#include
#include

intmain()
{
std::pairpair{1,2.0};
intnumber=3;
std::tupletuple(number);
constauto&[i,f]=pair;
//i=4;//error
constauto&[ri]=tuple;
ri=5;
}

如果結構化綁定i被聲明為const auto&,對應的類型為int,那么它應該是個const int&吧?i = 4;出錯了,看起來正是如此。但是如何解釋ri = 5;是合法的呢?

這個問題需要系統地從頭談起。先引入一個名字eE為其類型:

?expression是數組類型A,且ref-operator不存在時,Ecv A,每個元素由expression中的對應元素拷貝(= expression)或直接初始化({ expression }( expression )?否則,相當于定義eattr cv-auto ref-operator e initializer;

也就是說,方括號前面的修飾符都是作用于e的,而不是那些新聲明的變量。至于為什么第一條會獨立出來,這是因為在標準C++中第二條的形式不能用于數組拷貝。

然后分三種情況討論:

?數組情形,ET的數組類型,則每個結構化綁定都是指向e數組中元素的左值;被引類型(referenced type)為T;——結構化綁定是左值,不是左值引用:int array[2]{ 1, 2 }; auto& [i, j] = array; static_assert(!std::is_reference_v);?類元組情形,如果e是左值引用,則e是左值(lvalue),否則是消亡值(xvalue);記Tistd::tuple_element::type,則結構化綁定vi的類型是Ti的引用;當get返回左值引用時是左值引用,否則是右值引用;被引類型為Ti;——decltype對結構化綁定有特殊處理,產生被引類型,在類元組情形下結構化綁定的類型與被引類型是不同的;?數據成員情形,與數組類似,設數據成員mi被聲明為Ti類型,則結構化綁定的類型是指向cv Ti的左值(同樣不是左值引用);被引類型為cv Ti

至此,我想“結構化綁定”的意義已經明確了:標識符總是綁定一個對象,該對象是另一個對象的成員(或數組元素),后者或是拷貝或是引用(引用不是對象,意會即可)。與引用類似,結構化綁定都是既有對象的別名(這個對象可能是隱式的);與引用不同,結構化綁定不一定是引用類型。

(不理解的話可以參考N465911.5節,盡管你很可能會更加看不懂……)

現在可以解釋riconst的現象了:編譯器先創建了變量const auto& e = tuple;Econst std::tuple&std::tuple_element<0, E>::typeint&std::get<0>(e)同樣返回int&,故riint&類型。

在面向底層的C++編程中常用union和位域(bit field),結構化綁定支持這樣的數據成員。如果類有union類型成員,它必須是命名的,綁定的標識符的類型為該union類型的左值;如果有未命名的union成員,則這個類不能用于結構化綁定。

C++中不存在位域的指針和引用,但結構化綁定可以是指向位域的左值:

#include

structBitField
{
intf1:4;
intf2:4;
intf3:4;
};

intmain()
{
BitFieldb{1,2,3};
auto&[f1,f2,f3]=b;
f2=4;
autoprint=[&]{std::cout<

程序輸出:

143
153

f2的功能就像位域的引用一樣,既能寫回原值,又不會超出位域的范圍。

還有一些語法細節,比如get的名字查找、std::tuple_size沒有valueexplicit拷貝構造函數等,除非是深挖語法的language lawyer,在實際開發中不必糾結(上面這一堆已經可以算language lawyer了吧)。

局限

以上代碼示例應該已經囊括了所有類型的結構化綁定應用,你能想象到的其他語法都是錯的,包括但不限于:

?std::initializer_list初始化;因為std::initializer_list的長度是動態的,但結構化綁定的標識符數量是靜態的。?用列表初始化——auto [x,y,z] = {1, "xyzzy"s, 3.14159};;這相當于聲明了三個變量,但結構化綁定的意圖在于綁定而非聲明。?不聲明而直接綁定——[iter, success] = mymap.insert(value);;這相當于用std::tie,所以請繼續用std::tie。另外,由[開始可能與attributes混淆,給編譯器和編譯器設計者帶來壓力。?指明結構化綁定的修飾符——auto [& x, const y, const& z] = f();;同樣是脫離了結構化綁定的意圖。如果需要這樣的功能,或者一個個定義變量,或者手動寫上三要素。?指明結構化綁定的類型——SomeClass [x, y] = f();auto [x, std::string y] = f();;第一種可用auto [x, y] = SomeClass{ f() };代替;第二種同上一條。?顯式忽略一個結構化綁定——auto [x, std::ignore, z] = f();;消除編譯器警告是一個理由,但是auto [x, y, z] = f(); (void)y;亦可。這還涉及一些語言問題,請移步P0144R23.8節。?標識符嵌套——std::tuple, T4> f(); auto [ w, [x, y], z ] = f();;多寫一行吧。[同樣可能與attributes混淆。

以上語法都沒有納入C++20標準,不過可能在將來成為C++語法的擴展。

延伸

C++17的新特性不是孤立的,與結構化綁定相關的有:

?類模板參數推導(class template argument deduction,CTAD,由構造函數參數推導類模板參數;?拷貝省略(copy elision),保證NRV(named return value)優化;?constexprif,簡化泛型代碼,消除部分SFINAE;?帶初始化的條件分支語句:語法糖,使代碼更加優雅。


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 代碼
    +關注

    關注

    30

    文章

    4801

    瀏覽量

    68734
  • 編譯器
    +關注

    關注

    1

    文章

    1636

    瀏覽量

    49172
  • 結構化
    +關注

    關注

    0

    文章

    27

    瀏覽量

    10326

原文標題:聊聊結構化綁定

文章出處:【微信號:CPP開發者,微信公眾號:CPP開發者】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    結構化布線系統有哪些難題

      在布線系統中,結構化布線也是非常重要的一環,這里本文給大家主要講解了結構化布線系統的規劃、安裝以及投資成本等問題,希望對您有所幫助。  結構化布線系統規劃  大多數電纜廠商為它們的產品規定了15
    發表于 05-19 13:46

    TrustZone結構化消息是什么?

    大家好,我已閱讀任何與TrustZone相關的內容,但我無法弄清楚這兩個世界是如何相互溝通的。我所能找到的只是TrustZone API規范中的內容:客戶端和服務可以通過兩種機制進行通信:結構化
    發表于 03-20 08:58

    Deeplearningai結構化機器學習項目

    Deeplearningai 結構化機器學習項目 Week2 6-10
    發表于 05-18 15:12

    請問如何借助SC Express減少結構化測試次數?

    如何借助SC Express減少結構化測試次數?
    發表于 05-11 06:46

    怎么實現基于結構化方法的無線傳感器網絡設計?

    怎么實現基于結構化方法的無線傳感器網絡設計?
    發表于 05-31 06:34

    結構化設計分為哪幾部分?結構化設計的要求有哪些

    結構化設計分為哪幾部分?結構化設計的要求有哪些?結構化設計主要包括哪些部分?
    發表于 12-23 06:15

    結構化布線的綜合說明

    結構化布線的綜合說明 一、結構化布線系統簡介     隨著計算機和通信技術的飛速發展,網絡應用
    發表于 04-14 17:16 ?745次閱讀

    探究最佳的結構化ASIC設計方法

    由于與深亞微米標準單元ASIC相關的非重復性工程費用(NRE)越來越大,設計周期又很長,因此利用結構化ASIC進行定制IC設計的吸引力正變得越來越大。結構化ASIC能以極具競爭力的單位成
    發表于 05-02 10:39 ?1887次閱讀
    探究最佳的<b class='flag-5'>結構化</b>ASIC設計方法

    什么叫結構化的算法_算法和結構化數據初識

    結構化算法是由一些基本結構順序組成的,就是把一個大的功能的實現分隔為許多個小功能的實現。在基本結構之間不存在向前或向后的跳轉,流程的轉移只存在于一個基本的結構范圍內。一個非
    發表于 01-03 16:09 ?1.2w次閱讀
    什么叫<b class='flag-5'>結構化</b>的算法_算法和<b class='flag-5'>結構化</b>數據初識

    結構化布線系統的四點注意事項

    布線系統結構化 結構化布線 title=結構化布線結構化布線 title=結構化布線結構化布線系
    發表于 10-16 10:52 ?1244次閱讀

    安防監控視頻結構化那些事兒

    即便不考慮各個監控系統之間的信息關聯,光瀏覽這些視頻就需要花費大量的人力物力。解決這一問題的核心技術即視頻結構化描述技術,將海量視頻或圖片的非結構化數據提取并轉化為結構化信息描述。
    的頭像 發表于 03-20 10:20 ?3276次閱讀

    FPGA模塊設計與AlteraHardCopy結構化ASIC

    本文檔的主要內容詳細介紹的是FPGA模塊設計與AlteraHardCopy結構化ASIC。
    發表于 01-20 17:03 ?6次下載
    FPGA模塊<b class='flag-5'>化</b>設計與AlteraHardCopy<b class='flag-5'>結構化</b>ASIC

    CFD 設計利器:結構化和非結構化網格的組合使用

    在CFD的發展歷史中,結構化網格出現最早,至今仍在使用。結構化網格有幾個主要優點,如精度高、生成速度快、單元分布均勻。有些工具擅長繪制這類網格,例如CadenceFidelityAutomesh
    的頭像 發表于 12-23 08:12 ?2021次閱讀
    CFD 設計利器:<b class='flag-5'>結構化</b>和非<b class='flag-5'>結構化</b>網格的組合使用

    結構化布線的好處多嗎

    結構化布線是網絡系統中的重要組成部分,因為它為數據傳輸提供了強大、可擴展且可靠的基礎。通過遵守全球公認的標準,結構化布線可促進高速連接、簡化故障排除并確保未來的可擴展性。考慮到這些優勢,企業應優先
    的頭像 發表于 04-07 11:15 ?453次閱讀

    什么是結構化網絡布線?結構化網絡布線有哪些好處?

    在電纜領域,結構化網絡布線這個術語經常被提及。人們將其用作流行語,但它的真正含義是什么?結構化布線到底是什么? 為了了解真正的含義,讓我們看它的一些相關定義。 根據光纖協會的說法,結構化布線是由
    的頭像 發表于 04-11 11:54 ?540次閱讀
    主站蜘蛛池模板: 奇米奇米| 国产福利精品视频| 成人免费淫片95视频观看网站| 国产亚洲综合色就色| 国产精品国产主播在线观看| ts人妖在线| 天天干天天插天天操| 久久天天躁夜夜躁狠狠| 午夜黄色网| 美女被免费网站在线视频九色| 亚洲欧美日韩在线观看你懂的| 天堂资源中文在线| 女人被狂躁视频免费网站| 国产一级特黄生活片| 一级一片一a一片| 免费又爽又黄1000禁片| 91精品久久久久含羞草| 深夜看片在线观看18| 亚洲五月婷| 欧美色图首页| 波多野结衣在线观看一区二区| 天天爱夜夜| 男人的天堂黄色| 在线观看网址你懂得| 日本成人视屏| 成人av在线电影| 免费看国产精品久久久久| 中文字幕一区视频| 性大特级毛片视频| 久久久久久久综合色一本| 一级午夜免费视频| 97夜夜操| 一色桃子juy774在线播放| 欧美日韩国产在线一区| 91黄色影院| 国产精品夜夜春夜夜爽| 青青热久免费精品视频在线观看 | 亚洲综合在线观看一区www| 亚洲综合色一区二区三区小说| 欧美精品色精品一区二区三区| www.淫.com|