一文詳解C++17中的結(jié)構(gòu)化綁定
C++17中的結(jié)構(gòu)化綁定(structured binding):將指定名稱綁定到初始化程序的子對象或元素。簡而言之,它們使我們能夠從元組或結(jié)構(gòu)中聲明多個變量。與引用一樣,結(jié)構(gòu)化綁定是現(xiàn)有對象的別名;與引用不同,結(jié)構(gòu)化綁定不必是引用類型(reference type)。
C++17中結(jié)構(gòu)化綁定的主要目的是使代碼干凈且易于理解。結(jié)構(gòu)化綁定允許你在單個聲明中將多個變量綁定到結(jié)構(gòu)化對象的元素,例如std::tuple或struct。
每個結(jié)構(gòu)化綁定都有一個引用類型,該類型是decltype在應(yīng)用于無括號的結(jié)構(gòu)化綁定時返回的類型:E表示初始化表達式的類型
(1).binding an array:標識符的數(shù)量必須等于數(shù)組元素的數(shù)量;每個標識符的引用類型是數(shù)組元素類型; 注意:如果數(shù)組類型是cv限定的,那么它的元素類型也是cv限定的
int arr1[3] = { 1, 2, 3 }; auto [x, y, z] = arr1; // 拷貝 std::cout << "x:" << x << ",y:" << y << ",z:" << z << "\n"; // x:1,y:2,z:3 x = 4; std::cout << "arr1:" << arr1[0] << "\n"; // arr1:1 auto& [x2, y2, z2] = arr1; // 引用 std::cout << "x2:" << x2 << ",y2:" << y2 << ",z2:" << z2 << "\n"; // x2:1,y2:2,z2:3 x2 = 5; std::cout << "arr1:" << arr1[0] << "\n"; // arr1:5 const auto& [x3, y3, z3] {arr1}; const auto& [x4, y4, z4](arr1); std::cout << "x3:" << x3 << ",x4:" << x4 << "\n"; // x3:5,x4:5
(2).binding a tuple-like type:表達式std::tuple_size<E>::value必須是格式正確的整型常量表達式,并且標識符的數(shù)量必須等于std::tuple_size<E>::value
std::tuple<std::string, int, float> foo{ "csdn", 8, 6.6 }; const auto& [x3, y3, z3] = foo; std::cout << "x3:" << x3 << ",y3:" << y3 << ",z3:" << z3 << "\n"; // x3:csdn,y3:8,z3:6.6 auto& [x4, y4, z4] = foo; x4 = "github"; y4 = 6; z4 = 8.8; std::cout << "foo:" << std::get<0>(foo) << "," << std::get<1>(foo) << "," << std::get<2>(foo) << "\n"; // foo:github,6,8.8 int a = 1, b = 2; const auto& [x6, y6] = std::tie(a, b); // x6 and y6 are of type int& x6 = 6; auto [x7, y7] = std::tie(a, b); // x7 and y7 are still of type int& std::cout << "x7:" << x7 << ",a:" << a << "\n"; // x7:6,a:6 x7 = 8; std::cout << "x6:" << x6 << ",a:" << a << "\n"; // x6:8,a:8 if (&x6 != &x7) std::cout << "Error: &x6 != &x7\n"; // 不會執(zhí)行
(3).binding to data members:標識符的數(shù)量必須等于非靜態(tài)數(shù)據(jù)成員的數(shù)量
namespace { typedef struct Info { mutable std::string name; volatile int number; } Info; inline Info func() { return Info{ "csdn", 666 }; } typedef struct Data { int b{ 1 }, d{ 2 }, p{ 3 }, q{ 4 }; } Data; } // namespace const auto [x5, y5] = func(); std::cout << "x5:" << x5 << ",y5:" << y5 << "\n"; // x5:csdn,y5:666 x5 = "github"; //y5 = 888; //表達式必須是可修改的左值,需將const auto[x5, y5]調(diào)整為auto[x5, y5] const auto [b1, d1, p1, q1] = Data{}; std::cout << "b1:" << b1 << ",d1:" << d1 << ",p1:" << p1 << ",q1:" << q1 << "\n"; // b1:1,d1:2,p1:3,q1:4 const auto [b2, d2, p2, q2] = Data{ 4, 3, 2, 1 }; std::cout << "b2:" << b2 << ",d2:" << d2 << ",p2:" << p2 << ",q2:" << q2 << "\n"; // b2:4,d2:3,p2:2,q2:1 Data s; auto& [b3, d3, p3, q3] = s; std::cout << "b3:" << b3 << ",d3:" << d3 << ",p3:" << p3 << ",q3:" << q3 << "\n"; // b3:1,d3:2,p3:3,q3:4 b3 = 4, d3 = 3, p3 = 2, q3 = 1; std::cout << "s.b:" << s.b << ",s.d:" << s.d << ",s.p:" << s.p << ",s.q:" << s.q << "\n"; // s.b:4,s.d:3,s.p:2,s.q:1
注意:
(1).結(jié)構(gòu)化綁定無法受到約束;
(2).lambda表達式無法捕獲結(jié)構(gòu)化綁定(C++20中可以);
(3).必須確保在適當(dāng)?shù)臅r刻使用引用,盡量減少不必要的拷貝;
(4).使用結(jié)構(gòu)化綁定時,就不能再使用std::tie創(chuàng)建虛擬變量;
(5).結(jié)構(gòu)化綁定中有一個隱藏的匿名對象,結(jié)構(gòu)化綁定時引入的新變量名其實都指向這個匿名對象的成員/元素;
(6).可以在結(jié)構(gòu)化綁定中使用修飾符,如const和引用,這些修飾符會作用在新的匿名實體上,而不是結(jié)構(gòu)化綁定引入的新的變量名上;
(7).理論上講,結(jié)構(gòu)化綁定適用于任何有public數(shù)據(jù)成員的結(jié)構(gòu)體、C風(fēng)格數(shù)組和"類似元組(tuple-like)的對象";
(8).在任何情況下,結(jié)構(gòu)化綁定中聲明的變量名的數(shù)量都必須和元素或數(shù)據(jù)成員的數(shù)量相同;
(9).使用結(jié)構(gòu)化綁定需要繼承時需要遵循一定的規(guī)則:所有的非靜態(tài)數(shù)據(jù)成員必須在同一個類中定義(也就是說,這些成員要么是全部直接來自于最終的類,要么是全部來自同一個父類);并且只有當(dāng)public成員的順序保證是固定的時候你才應(yīng)該使用結(jié)構(gòu)化綁定;
(10).結(jié)構(gòu)化綁定機制是可拓展的,你可以為任何類型添加對結(jié)構(gòu)化綁定的支持。標準庫中就為std::pair<>、std::tuple<>、std::array<>添加了支持;
const std::map<std::string, std::string> addrs{ {"csdn", "https://blog.csdn.net/fengbingchun/"}, {"github", "https://github.com/fengbingchun"} }; for (const auto& [key, val] : addrs) { std::cout << "key: " << key << ", addr: " << val << "\n"; // key: csdn, addr: https://blog.csdn.net/fengbingchun/ // key: github, addr: https://github.com/fengbingchun } Info info{ "github", 888 }; auto&& [u, v] = std::move(info); // u和v指向的匿名實體是info的右值引用,同時info仍持有值 std::cout << "info.name:" << info.name << "\n"; // info.name:github Info info2{ "csdn", 666 }; auto [u2, v2] = std::move(info2); // info2已失去了值 std::cout << "info2.name:" << info2.name << "\n"; // info2.name:
執(zhí)行結(jié)果如下圖所示:
GitHub:https://github.com/fengbingchun/Messy_Test
到此這篇關(guān)于一文詳解C++17中的結(jié)構(gòu)化綁定的文章就介紹到這了,更多相關(guān)C++17結(jié)構(gòu)化綁定內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Qt實現(xiàn)指針式時鐘 Qt實現(xiàn)動態(tài)時鐘
這篇文章主要為大家詳細介紹了Qt實現(xiàn)指針式時鐘,Qt實現(xiàn)動態(tài)時鐘,兩者相互切換,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-07-07C++?Boost?CircularBuffer算法超詳細精講
Boost是為C++語言標準庫提供擴展的一些C++程序庫的總稱。Boost庫是一個可移植、提供源代碼的C++庫,作為標準庫的后備,是C++標準化進程的開發(fā)引擎之一,是為C++語言標準庫提供擴展的一些C++程序庫的總稱2022-11-11