開啟章節選單
Tuple
普通介紹
在上一章我們學會了 pair
,但你有沒有曾經想要放超過兩項資料呢?其中一個作法就是套兩層 pair
,不過很顯然的這樣寫起來會很麻煩,這時候就輪到 tuple
派上用場了!tuple
的概念與 pair
差不多,不過能夠存放更多的資料不限於兩個。這個容器主要用在將不同型態但又有關聯的資料結合在一起,存取的寫法跟過往的容器或型態有較大的不同,撰寫上較需特別留意。
初始化
tuple
作為 std
中的一員,在使用前需要引入 <tuple>
才能使用,當然如果你已經引入 <bits/stdc++.h>
就不需要再引入了。
#include <tuple>
今天我們假設要記錄一位學生的資訊,我們會需要紀錄他的座號、姓名以及考試的分數。這裡總共有三個項目,且都是不同的資料型態,這時就可以這樣寫:
tuple<int, string, float> t1; // 宣告但未初始化 tuple<int, string, float> t2(14, "YD", 94.5); // 宣告並初始化
首先在最前面寫上 tuple
,接著在角括號中填入要儲存的資料型態,緊接著 t
是這個 tuple
的名稱。後方的括號可寫也可不寫,主要是用來在宣告時做初始化用的,若資料在宣告後才會獲取,也可以於事後透過下面的方法存入:
t = make_tuple(14, "YD", 94.5);
或者是使用 {}
來代替 make_tuple
:
t = {14, "YD", 94.5};
這樣就可以將資料存入 tuple
中,不過也跟 pair 一樣,必須要注意型態是否明確,否則可能會出現錯誤。
存取與修改
tuple
的讀取方式跟過往的讀取有比較大的差異,其中一種做法就是使用 get
函式,我們需在角括號中填入存取的位置(跟陣列的 index 一樣都是從 0 開始),以及於小括號中填入 tuple
的名稱。具體寫法如下:
get<位置>(名稱)
舉例來說,若我們要讀取 t
中的前兩筆資料,可以這樣寫:
tuple<int, string, float> t(14, "YD", 94.5); cout << get<0>(t) << endl; // 14 cout << get<1>(t) << endl; // YD
若要修改 tuple
中的資料,可以使用 get
函式取出資料後再進行修改:
tuple<int, string, float> t(14, "YD", 94.5); get<0>(t) = 15; get<1>(t) = "Dio"; cout << get<0>(t) << endl; // 15 cout << get<1>(t) << endl; // Dio
或許看起來很不直覺?為什麼明明是 get
函式卻可以直接修改資料呢?這是因為 get
函式實際上是回傳一個 reference,所以我們可以透過這個 reference 來修改資料。
解構 tuple
就跟 pair
一樣,若我們想要一次讀取 tuple
中的所有資料,我們可以使用 tie
函式,這會將 tuple
中的資料解構依序塞入 tie
中的各個變數中,每個變數的型態都要與宣告時相同:
// 先宣告變數 int a; string b; float c; // 解構 tuple tie(a, b, c) = t;
有時有些數值我們並沒有要使用,這時我們就可以使用 ignore
來忽略該數值,這樣就可以避免宣告過多無意義變數:
// 如果不需要中間的數值 tie(a, ignore, b) = t; cout << a << ' ' << b << endl; // 1 3
tuple 的比較
tuple
也可以進行比較,不過要注意的是 tuple
的比較是從第一個元素開始比較,若第一個元素相同則比較第二個元素,一直往後比較到發現不同為止。若所有元素都相同則兩個 tuple
判斷為相等。若要比較 tuple
,可以使用 ==
、 !=
、 <
、 >
、 <=
、 >=
這些運算子:
tuple<int, int, int> t1(1, 2, 3); tuple<int, int, int> t2(1, 3, 3); tuple<int, int, int> t3(2, 2, 3); cout << (t1 == t2) << endl; // false cout << (t1 != t2) << endl; // true cout << (t1 < t2) << endl; // true cout << (t1 > t2) << endl; // false cout << (t1 <= t2) << endl; // true
取得 tuple 的元素數量
如果你想知道 tuple
中有幾個元素,可以使用 tuple_size
這個函式:
tuple<int, string, float> t(14, "YD", 94.5); cout << tuple_size<decltype(t)>::value << endl; // 3
decltype
是一個用來取得變數型態的函式,這邊的 decltype(t)
就是取得 t
的型態,換句話說我們也可以這樣寫:
cout << tuple_size<tuple<int, string, float>>::value << endl; // 3
小測驗
下列哪個作法可以取得 tuple<int, int, int> t = {1, 2, 3};
中的第二個元素(也就是 2)?