C++(STL):02---tuple容器

2021-03-02 遊戲開發司機
一、tuple的歷史概述二、tuple概述tuple的實現

支持的操作

三、定義和初始化tuple

std::tuple<size_t, size_t, size_t> threeD; //使用默認構造函數

std::tuple<std::string, std::vector<double>, int, std::list<int>>

someVal("constants", { 3.14,2.718 }, 42, { 0,1,2,3,4,5 });

string s;

tuple<string&> t(s);

get<0>(t) = "hello"; //s變為hello

Tuple和初值列

template<typename... Args>

void foo(const std::tuple<Args...> t);

int main()

{

foo(42); //錯誤,禁止隱式轉換

foo(make_tuple(42)); //正確

return 0;

}

std::tuple<size_t, size_t, size_t> threeD1 = { 1,2,3 }; //錯誤,不能進行隱式類型轉換了

std::tuple<size_t, size_t, size_t> threeD2{ 1,2,3 }; //正確

std::vector<std::tuple<int, float>> v{ { 1,1,0 },{2,2,0} }; //錯誤

std::tuple<int, int, int> foo() { //錯誤

return{ 1,2,3 };

}

auto item = std::make_tuple("0-999-78345-X", 3, 20.00);

//item類型為tuple<const char*, int, double>

四、訪問tuple成員get()函數

auto item = std::make_tuple("0-999-78345-X", 3, 20.00);

auto book = std::get<0>(item); //返回item第一個成員

auto cnt = std::get<1>(item); //返回item第二個成員

auto price = std::get<2>(item) / cnt; //返回最後一個成員,並將其除以cnt

std::get<2>(item) *= 0.8; //打折20%(get返回的是item的引用)

std::tuple<int,double> t1;

get<0>(t1); //正確

int i;

get<i>(t1); //錯誤,運行期才傳入一個索引值

get<3>(t1); //錯誤,索引錯誤,t1隻有兩個元素

tuple_size類模板、tuple_element類模板、tuple_cat類模板

//item的類型為tuple<const char*, int, double>

auto item = std::make_tuple("0-999-78345-X", 3, 20.00);

//trans為item的數據類型

typedef decltype(item) trans;

//返回item中的數據成員數量

size_t sz = std::tuple_size<trans>::value;

//type為int

std::tuple_element<1, trans>::type cnt = get<1>(item);

int n;

//tt的類型為tuple<int,double,std::string,int>

auto tt = std::tuple_cat(std::make_tuple(42, 7.7, "hello"), std::tie(n));

五、關係和相等運算符

下面是STL容器的比較規則:

如果兩個容器具有相同大小且所有元素都兩兩對應相等,則兩容器相等;否則不相等

如果兩個容器大小不相同,但較小容器中每個元素都等於較大容器中對應元素,則較小容器小於較大容器

如果兩個容器都不是另一個容器的前綴子序列,則它們的比較結果取決於第一個不相等元素的比較結果

tuple與STL容器的比較規則類似,但是:

只有兩個tuple具有相同數量的成員時才可以進行比較

為了使用相等或不等運算符,對每對成員相等或不等運算符都必須是合法的

類似的為了使用關係運算符,對每對成員使用關係運算符也必須是合法的

例如:

std::tuple<std::string, std::string> duo("1", "2");

std::tuple<size_t, size_t> twoD(1, 2);bool b = (duo == twoD);

std::tuple<size_t, size_t, size_t> threeD(1, 2, 3);b = (twoD < threeD);

std::tuple<size_t, size_t> origin(0, 0);b = (origin > twoD);

六、make_tuple()函數、tie()函數make_tuple()

//三個元素的類型是int、int、const char*

make_tuple(22, 44, "nico");

//其實第三個元素的類型為const char[5]。當使用type trait std::decay()時,第三個元素的類型衰退為const char*

std::string s;

auto x = std::make_tuple(s); //以s的非引用創建一個tuple

std::get<0>(x) = "my value"; //未改變s的值

auto y = make_tuple(ref(s)); //以s的引用創建一個tuple

std::get<0>(y) = "my value"; //改變s的值

tie()

std::tuple<int, float, std::string> t(77, 1.1, "more light");

int i;

float f;

std::string s;

std::tie(i, f, s) = t;

//將t賦值給一個tuple對象(tie()創建返回的tuple),其中都使用i,f,s的引用來創建

//因此,創建之後,i=77,f=1.1,s="more light"

std::tuple<int, float, std::string> t(77, 1.1, "more light");

int i;

std::string s;

//使用t創建一個tuple,tuple的類型為tuple<int,std::string>,其中忽略了t的第二個元素

std::tie(i, std::ignore, s) = t;

七、tuple的輸入/輸出八、使用tuple返回多個值

#include <iostream>#include <ostream>#include <sstream>#include <fstream>#include <string>#include <iterator>#include <vector>#include <tuple>#include <algorithm>#include <numeric>using namespace std;

struct Sales_data {std::string isbn()const { return bookNo; }Sales_data(const string& s) :bookNo(s), units_sold(0), revenue(0) {}

Sales_data &operator+=(const Sales_data &rhs) {units_sold += rhs.units_sold;revenue += rhs.revenue;return *this;}

std::string bookNo;unsigned units_sold = 0;double revenue = 0.0;};

ostream &operator<<(ostream &os, const Sales_data &item){os << item.isbn() << " " << item.units_sold << " " << item.revenue << ;return os;}

Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs) {Sales_data sum = lhs;sum += rhs;return sum;}

/*

vector<Sales_data>代表一家書店的銷售情況

vector<vector>代表所有書店

*/

vector<vector<Sales_data>> files;

編寫一個返回tuple的函數:

在指定的迭代器區間內尋找參數3所指定的元素

該算法默認使用<運算符來比較,因為Sales_data沒有<運算符,因此我們傳遞給它一個名為compareIsbn函數的指針

該算法返回一個pair,表示元素的範圍。如果未找到,則兩個迭代器相等,表示空範圍

下面我們編寫一個函數,對於一本給定的書,在files中搜索出售過這本書的書店

對每家有銷售記錄的,返回一個tuple類型,保存這家書店的索引和兩個迭代器(索引指出書店在files中的位置,迭代器分別標記書籍在此書店的vector<Sales_data>中第一條銷售記錄和最後一條銷售記錄之後的位置)

equal_range算法:

bool compareIsbn(const Sales_data& lhs, const Sales_data& rhs){return lhs.isbn() < rhs.isbn();}

vector<vector<Sales_data>> files;

typedef tuple<vector<Sales_data>::size_type,vector<Sales_data>::const_iterator,vector<Sales_data>::const_iterator> matches;

vector<matches> findBook(const vector<vector<Sales_data>> &files, const string &book){vector<matches> ret;

for (auto it = files.cbegin(); it != files.cend(); ++it){auto found = equal_range(it->cbegin(), it->cend(), book, compareIsbn);

if (found.first != found.second)ret.push_back(std::make_tuple(it - files.cbegin(), found.first, found.second));}

return ret;}

使用函數返回tuple:

while循環從in中讀取名為s的書籍,然後調用上面的findBook函數來查找是否有名為s的書籍

如果沒有,則findBook返回的vector為空,那麼使用continue繼續循環

如果查找到了,使用for循環遍歷trans的vector,其中每個元素都是一個tuple

然後使用get得到tuple中的0、1、2三種元素並列印

其中使用了accumulate算法(由於我們定義了Sales_data的加法運算符,因此可以使用這個算法)。accumulate以參數3為初始值,其中使用Sales_data的參數為string的構造函數來構造。又由於我們定義了Sales_data的<<運算符,因此可以輸出到ostream中

void reportResults(istream &in, ostream &os, const vector<vector<Sales_data>> &files){std::string s; 

while (in >> s){auto trans = findBook(files, s);

if (trans.empty()) {std::cout << s << "not found in any stores" << std::endl;continue;}else {for (const auto &store : trans) {os << "store: " << std::get<0>(store) << std::endl;os << "sales: " << std::accumulate(std::get<1>(store), std::get<2>(store), Sales_data(s)) << std::endl;}}}}

九、自定義列印tuple

 

演示案例:

#include "printtuple.hpp"#include <tuple>#include <iostream>#include <string>using namespace std;int main(){    tuple <int,float ,string> t(77,1.1, "more light");    cout<< "io: " <<t << endl;}

相關焦點

  • 數據容器 tuple
    數據容器 tuple數據容器之tuplelist 定義 list基本概念 tuple是Python中另外最基本的數據結構。序列中的每個元素都分配一個索引index - 它的位置,或索引,第一個索引是0,第二個索引是1,依此類推。
  • 跟我學C++中級篇——STL的學習
    一、c++標準庫C++的標準庫主要包含兩大類,首先是包含C的標準庫的,當然,為了適應c++對一些C庫進行了少許的修改和增加。最重要的當然是面向對象的c++庫;而c++庫又可以分成兩大類,即面向對象的c++庫和標準模板庫,也就是題目中的STL。
  • C++隨機排序容器中的元素
    作者:apocelipes連結:https://www.cnblogs.com/apocelipes/p/10351335.html在各種程序語言中都提供了將容器元素隨機排序的shuffle方法,c++也不例外。
  • C 語言會比 C++ 快?
    我們將看一下實現的幾個變化過程,首先是從使用 C ++ 容器和算法的變化開始,這將有助於該算法,然後一次刪除一個 C ++ 特性並測試編譯速度和運行時的性能。與之相反的是,使用自定義容器,可以輕鬆地選擇跳過初始化。實際上,在我們的替換代碼中這是唯一的選項,因為如果需要,可以很輕鬆的手動添加 memset 設置數組大小。又回到了之前帶有邊界檢查的 operator[] 的自定義容器大部分都是成功的,但它並不能讓我滿意。
  • ​跟我學C++中級篇——STL的容器vector
    一、順序容器vectorC++程式設計師中,如果用到過STL,那麼一定肯定用過vector,這個是最常見,最初步的一個數據類型。上一篇提到的array遠遠比不上它。畢竟那玩意兒相對vector是很久遠後才提出來的。在這之前,std::vector承擔了多少小菜鳥處理數組各種問題的最優選方法。不用處理內存,可以刪除,任意增加不考慮越界。那簡直是一種最單純質樸的快樂。
  • 跟我學C++中級篇——STL中的字符串
    它不算是STL的容器,它只是一個類。         }         void swap(mystring& mstr)         {            std::swap(str_, mstr.str_);         } private:     char* str_;};這個是參考《Effect c++
  • C++提高第三篇2 STL常用容器 vector
    = v.end(); it++) { cout << *it << " "; } cout << endl;}函數printVector後文多次使用,列印示例中vector容器的數據。
  • 淺談C++下STL庫中的容器底層小知識
    STL中現成的容器、算法在刷牛客上的算法題的時候簡直不要太好使。可是對於在大廠面試過程中,STL庫中各種容器底層數據結構以及相關實現細節也是常問的知識點,今天就帶大家小小梳理一番STL中的常見容器下的一些小知識吧,希望能對大家有所幫助。
  • C++14新特性的所有知識點全在這兒啦!
    using namespace std;auto func(int i) { return i;}int main() { cout << func(4) << endl; return 0;}使用C++11編譯:~/test$ g++ test.cc -std=c++
  • c++11新特性,所有知識點都在這了!
    c++11新特性吧,你是怎麼回答的呢?,然而這種問題其實都可以通過c++11引入的智能指針來解決,相反我還認為這種內存管理還是c++語言的優勢,因為盡在掌握。std::unordered_map:基於hash表實現的map,內部不會排序,使用方法和set類似std::array:數組,在越界訪問時拋出異常,建議使用std::array替代普通的數組std::tuple
  • C++ STL快速入門
    STL容器是STL學習中要重點關注的,STL容器有兩大類,順序容器和關聯容器。順序容器有可變長動態數組vector、雙端隊列deque、雙向鍊表list,它們之所以被稱為順序容器,是因為元素在容器中的位置同元素的值無關,即容器不是排序的。將元素插入容器時,指定在什麼位置(尾部、頭部或中間某處)插入,元素就會位於什麼位置。
  • C++ 的門門道道 | 技術頭條 - CSDN
    九、內存拷貝小心內存越界memcpy,memset有很強的限制,僅能用於POD結構,不能作用於stl容器或者帶有虛函數的類。帶虛函數的類對象會有一個虛函數表的指針,memcpy將破壞該指針指向。>十、用sprintf格式化字符串時,類型和格式化符號要嚴格匹配因為sprintf的函數實現裡是按格式化串從棧上取參數,任何不一致,都有可能引起不可預知的錯誤; /usr/include/inttypes.h裡定義了跨平臺的格式化符號,比如PRId64用于格式化int64_t十一、stl
  • 元組(tuple)-Python基本數據類型之四
    在python中,元組這種數據結構同列表類似,都可以描述一組數據的集合,它們都是容器,是一系列組合的對象,不同的地方在於,元組裡的元素是不能更改的,它們之間的差異性我們用一個例子來說明一下:列表:) #計算元組元素個數>>>student= (1, "tom", "2008-05-06", 10, 135.7)>>>print(len(student)) #輸出 5max(tuple)#返回元組中元素最大值>>
  • C++ 優先隊列priority_queue
    這三個參數的含義分別為:數據類型,容器類型和比較函數,實際上優先隊列就是維護了一個裝有 T 類型元素的容器 Container,並在入隊和出隊時對容器內元素使用 Compare 比較函數進行了排序。這3個參數還要滿足一定的要求,並且在使用過程中有些注意事項:1.
  • C++ STL詳解(1)
    STL 從根本上講是「容器」的集合,也是組件的集合。容器包括 list、vector、set、map 等;組件包括迭代器等。STL 的目的是標準化組件。 STL 是 C++ 的一部分,不用額外安裝,被內建在支持 C++ 的編譯器中。STL 的算法是標準算法,其實現了將已經定義好的算法應用在容器的對象上。
  • C++ STL詳解(4)
    來源:blog.csdn.net/qq_41575507/article/details/113939257刷題時常用的STLunordered_set / unordered_multiset 這兩個容器的方法與上一篇
  • 從零開始學Python-Day9-集合list和元組tuple
    如果一個list為空,即裡面沒有元素,那麼他的長度也就len應該等於0tupletuple叫做元組,它跟list最大的區別就是一旦初始化就不允許再變化,所謂初始化就是給它賦值。tuple的不可變性強調了數據的安全性,對於不需要用戶交互變化的量,最好用tuple,能不用list就不用。
  • Python的List與Tuple
    Tuple(元組)元組(tuple)與列表類似,不同之處在於元組的元素不能修改。元組寫在小括號 () 裡,元素之間用逗號隔開。元組中的元素類型也可以不相同:/usr/bin/python3tuple = ( 'abcd', 786 , 2.23, 'runoob', 70.2 )tinytuple = (123, 'runoob')print (tuple) # 輸出完整元組print (tuple[0]) # 輸出元組的第一個元素print
  • 【C++面試知識】C++11新特性
    . */ });4.變長參數的模板C++11中引入了變長參數模板,發明了新的數據類型:tuple,tuple是一個N元組。能夠傳入1個, 2個甚至多個不同類型的數據auto t1 = make_tuple(1, 2.0, "C++ 11");auto t2 = make_tuple(1, 2.0, "C++ 11", {1, 0, 2});5.更加優雅的初始化方法在C++11之前,只有數組能使用初始化列表