国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)

這篇具有很好參考價值的文章主要介紹了C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

侯捷 C++八部曲筆記匯總 - - - 持續(xù)更新 ! ! !
一、C++ 面向對象高級開發(fā)
1、C++面向對象高級編程(上)
2、C++面向對象高級編程(下)
二、STL 標準庫和泛型編程
1、分配器、序列式容器
2、關聯(lián)式容器
3、迭代器、 算法、仿函數(shù)
4、適配器、補充
三、C++ 設計模式
四、C++ 新標準
五、C++ 內(nèi)存管理機制
六、C++ 程序的生前和死后

使用一個東西,卻不明白它的道理,不高明!—— 林語堂

階段學習
使用C++標準庫
認識C++標準庫(胸中自有丘壑?。?br> 良好使用C++標準庫
擴充C++標準庫

所謂 Generic ProgrammingGP,泛型編程),就是使用 template (模板)為主要工具來編寫程序。

  • GP 是將 datasmethods 分開來;

    • ContainersAlgorithms可各自閉門造車﹐其間以Iterator連通即可·
    • Algorithms通過Iterators確定操作范圍﹐也通過Iterators取用 Container元素。
  • OOP(Object-Oriented Programming),企圖將 datasmethods 關聯(lián)在一起。

C++標準模板庫Standard Template 最重要的六大部件(Components):容器算法、仿函數(shù)迭代器、適配器分配器

  • 容器(Containers)是class template
  • 算法(Algorithms)是function template其內(nèi)最終涉及元素本身的操作,無非就是比大小!)
  • 迭代器(Iterators)是class template
  • 仿函數(shù)(Functors)是class template
  • 適配器(Adapters)是class template
  • 分配器(Allocators)是class template

關系圖:
C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)

適配器(Adapters)

可以把它理解為改造器,它要去改造一些東西;也可以理解為實現(xiàn)換膚功能

已經(jīng)存在的東西,改接口,改函數(shù)名等。。。

C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)

實現(xiàn)適配,可以使用繼承(is a)、復合(has a) 的兩種方式實現(xiàn)。
共性:STL使用 復合(has a) 來實現(xiàn)適配!

容器適配器(Container Adapters)

例如:stackqueue

具體定義查看:序列式容器的stackqueue容器

  • 只使用一部分以及改接口,改函數(shù)名等。。。
  • 復合(內(nèi)涵) 的東西換一個風貌換一種風格出來!

仿函數(shù)適配器(Functor Adapters)

bind2nd(綁定第二實參)

把東西記起來,以備后面使用!

可以看到下面的這個例子,使用算法count_if:

  • 第三個參數(shù)是一個predicate,也就是判斷條件,有一個仿函數(shù)對象less<int>(),但是他被仿函數(shù)適配器bind2nd(將less的第二個參數(shù)綁定為 40)和 not1(取反)修飾,從而實現(xiàn)判斷條件為是否小于40

C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)
bind2nd調(diào)用binder2nd:

  • 圖上灰色的東西就是仿函數(shù)適配器仿函數(shù)之間的問答!
    • 這里就體現(xiàn)了仿函數(shù)為什么要繼承適合的unary_function或者binary_function等類的原因!
  • 還有一個細節(jié):適配器適配之后的仿函數(shù)也能夠繼續(xù)被適配:
    • 所以適配器要繼承unary_function或者binary_function等類,這樣才能回答另外一個適配器的問題。
    • 問 bianry_fucntion 三個參數(shù)first_argument_type、second_argument_type、result_type。
    • 提問前面都要加上typename,是為了讓編譯通過!
  • 所以,仿函數(shù)必須能夠回答適配器的問題,這個仿函數(shù)才是可適配的!

相對綁定第二實參,綁定第一實參bind1st

not1

對一個Predicate取反。

  • not1是構造一個與謂詞結果相反的一元函數(shù)對象。
  • not2是構造一個與謂詞結果相反的二元函數(shù)對象。

一層套一層,像樂高積木一樣!

C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)

bind(新型適配器)

替換了一些過時(bind1st、bind2st)的仿函數(shù)適配器!

C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)
std::bind 可以綁定:

  1. functions
  2. function objects
  3. member functions,_1(占位符號)必須是某個object地址。
  4. data members,_1必須是某個object地址。

返回一個function object ret。調(diào)用ret相當于調(diào)用上述的1,2,3或者相當于取出4.

示例:

// bind example
#include <iostream>     // std::cout
#include <functional>   // std::bind

// a function: (also works with function object: std::divides<double> my_divide;)
double my_divide (double x, double y) {return x/y;}

struct MyPair {
  double a,b;
  double multiply() {return a*b;}
};

int main () {
  // 占位符的使用方法!?。。。。。?!
  using namespace std::placeholders;    // adds visibility of _1, _2, _3,...
  
  //---------------------綁定function,也就是前面的1---------------------
  // binding functions:
  auto fn_five = std::bind (my_divide,10,2);               // returns 10/2
  std::cout << fn_five() << '\n';                          // 5

  auto fn_half = std::bind (my_divide,_1,2);               // returns x/2
  std::cout << fn_half(10) << '\n';                        // 5

  auto fn_invert = std::bind (my_divide,_2,_1);            // returns y/x
  std::cout << fn_invert(10,2) << '\n';                    // 0.2

  auto fn_rounding = std::bind<int> (my_divide,_1,_2);     // returns int(x/y)
  std::cout << fn_rounding(10,3) << '\n';                  // 3

  MyPair ten_two {10,2};

  //---------------------綁定member functions,也就是前面的3---------------------
  // binding members:
  //member function 其實有一個看不見的實參argument :this
  auto bound_member_fn = std::bind (&MyPair::multiply,_1); // returns x.multiply()
  std::cout << bound_member_fn(ten_two) << '\n';           // 20

  //---------------------綁定member data,也就是前面的4---------------------
  auto bound_member_data = std::bind (&MyPair::a,ten_two); // returns ten_two.a
  std::cout << bound_member_data() << '\n';                // 10


  //-------------------------上面的bind2nd就可以替換了-------------------------
  vector<int> v {15, 37, 94, 50, 73, 58, 28, 98};
  int n = count_if(v.cbegin(), v.cend(), not1(bind2nd(less<int>(), 50)))
  cout << "n=" << n << endl; //5

  //替換
  auto fn_ = bind(less<int>(), _1, 50);
  cout << count_if(v.cbegin(), v.cend(), fn_) << endl;   //3
  
  return 0;
}

迭代器適配器(Iterator Adapters)

reverse_iterator

reverse_iterator
rbegin(){//取逆向的頭,就是正向的尾巴
	return reverse_iterator(end());
}
	
reverse_iterator
rend(){//取逆向的尾巴,就是正向的頭
	return reverse_iterator(begin());
}

也有五種關聯(lián)類型:

C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)

inserter

可以不用擔心copy到的目的容器大小不匹配的問題。
copy是寫死的,我們調(diào)用copy,希望完成在容器指定位置插入一些值!具體的實現(xiàn):

  • 把相應的容器和迭代器傳入inserter,對容器的迭代器中的 = 運算符進行重載,就能改變copy的行為!
  • 因為這個是對迭代器的 = 運算符行為進行重定義,所以是迭代器的適配器

C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)

X適配器

X表示未知:(容器、迭代器、函數(shù),三大類之外的!)

  • 包括ostream、istream迭代器適配器

ostream_iterator

  • copy都是已經(jīng)寫好的,不能再改了!
  • 該適配器適配的是basic_ostream,也是重載了 = 運算符,添加輸出操作!

C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)

istream_iterator

ostream_iterator的兄弟,cin >> x被替換為了 x = *iit ,適配 basic_istream。

  • 不斷++,就不斷讀內(nèi)容。

C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)
copy都是已經(jīng)寫好的,不能再改了!

當創(chuàng)建iit(cin),已經(jīng)讀入數(shù)據(jù)了!
不斷++,就不斷讀內(nèi)容。

C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)

補充

標準庫STL周邊還有一些東西需要知道。

Hash Function

如果有一個我們自己的類,我們要怎么給這個類設計hash函數(shù)呢?

C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)

使用類中的成員變量的hash函數(shù)得到hash值,然后相加,(下面左上角)這個太naive了,可能會產(chǎn)生很多沖突。
所以使用右邊那個!

  • args是C++11的新特性,任意多個參數(shù)都行,n個參數(shù)的args作為另外一個函數(shù)的輸入的時候
    • 先調(diào)用①,分配一個種子seed,再調(diào)用②;
    • 在②里面拆分args,拆分成1 + n-1 的形式,遞歸調(diào)用自身,直到args只剩下一個參數(shù)時,調(diào)用③;
    • 在②中拆分時,會不斷改變種子seed基本類型的hash函數(shù) + 0x9e3779b9 + ... (越亂越好,沒有數(shù)學可言,)。

也是使用想法一的思想,但是加入了更多的復雜的操作,使得得到的hash code沖突更少。

C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)

tuple

一組東西的組合,可以任意指定多少個元素,這些元素可以是任意的類型。

使用示例:

tuple<string, int, int, complex<double>> t;
sizeof(t); // 32, 為什么是32,而不是28呢?啊~侯捷也無法理解??!

tuple<int, float, string> t1(41, 6.3, "test");
cout << "t1:" << get<0>(t1) << ' ' << get<1>(t1) << ' ' << get<2>(t1) << endl;

auto t2 = make_tuple(22, 44, "test2"); // t2也是一個tuple,自動推導類型

tuple_size< tuple<int, float, string> >::value; // 3
tuple_element< tuple<int, float, string> >::type; // 取tuple里面的類型

繼承的是自己,會自動形成一個類的繼承關系,注意有一個空的 tuple 類。

C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)

type traits

trivial:瑣碎的,平凡的,平淡無奇的,無關痛癢的,無價值的,不重要的。

泛化模板類,包括五種比較重要的typedef: 默認的回答都是重要的!

typedef _false_type has_trivial_default_constructor; 		//默認構造函數(shù)是不重要嗎?
typedef _false_type has_trivial_copy_constructor;			//拷貝構造函數(shù)是不重要嘛?
typedef _false_type has_trivial_assignment_operator;		//拷貝賦值構造函數(shù)是不重要嘛?
typedef _false_type has_trivial_destructor;					//析構函數(shù)是不重要嘛?
typedef _false_type is_POD_type;							//是不是舊格式(struct,只有數(shù)據(jù),沒有方法)?

比如說對于inttype traits,五個問題的回答都不重要。一般是算法會對traits進行提問。實用性不高。

C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)
type traits

現(xiàn)在的 traits機 ,非常智能:

  • 只要把自己寫的或者系統(tǒng)自帶的類,作為 is_()::value 就能得到問題的答案,這些問題包括下面幾種,不全:

測試:

//global function template
template <typename T>
void type_traits_output(const T& x)
{
	cout << "\ntype traits for type:" << typeid(T).name() << endl;
	
	cout << "is_void\t" << is_void<T>::value << endl;
	cout << "is_integral\t" << is_integral<T>::value << endl;
	cout << "is_array\t" << is_array<T>::value << endl;
	cout << "is_class\t" << is_class<T>::value << endl;
	cout << "is_function\t" << is_function<T>::value << endl;
	cout << "is_pointer\t" << is_pointer<T>::value << endl;
	cout << "is_object\t" << is_object<T>::value << endl;
	...
}

C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)
C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)

類型萃取機這么強的功能,是怎么實現(xiàn)的呢?下面以is_void為例:

  • 首先去掉 constvolatile 這兩種對得到類特征無用的修飾關鍵字,做法如下(主要是用模板技巧);
  • 然后將去掉 cv (就是constvolatile )關鍵字之后,再傳入 __is_void_helper 模板類中,讓其自己匹配是不是空類型,匹配到不同的模板類,返回不同的bool值。

C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)

cout

是一個對象object,不是一個類,源碼如下:

  • 想要用cout輸出自己的類型,就可以重載 << 運算符。

C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)

movable

movable元素會對各種容器的速度效能產(chǎn)生影響?。?!
vector的增長方式,對vector的影響很大,對其他的容器影響不是很大!

moveable 指的是 move 構造、move 賦值

  • move():是一種淺層拷貝,當用 a 初始化 b 后,a 不再需要時,最好是初始化完成后就將 a 析構,使用 move 最優(yōu)。
  • 如果說,我們用 a 初始化了 b 后,仍要對 a 進行操作,用這種淺層復制的方法就不合適了。

所以C++引入了移動構造函數(shù),專門處理這種,用 a 初始化 b 后,就將 a 析構的情況。這種操作的好處是:

  • a 對象的內(nèi)容復制一份到 b 中之后,b 直接使用 a 的內(nèi)存空間,這樣就避免了新的空間的分配,大大降低了構造的成本。這就是移動構造函數(shù)設計的初衷。

move的使用場景是:原來的對象不再使用。如果再用就很危險?。?!

C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)

C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)

測試函數(shù):

移動構造函數(shù)實現(xiàn)是:調(diào)用拷貝構造函數(shù),但是會將原來的對象中的成員變量置0!這樣就不會調(diào)用原對象的析構函數(shù)了!如下圖加深的部分,而且用的是引用的引用 && !&&右值引用,右值有一個很重要的性質:只能綁定到一個將要銷毀的對象。

調(diào)用移動構造函數(shù)方法,顯示調(diào)用move:classObj_1(std::move(classObj_2))

move焊copy:

C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)

注:僅供學習參考,如有不足,歡迎指正!文章來源地址http://www.zghlxwxcb.cn/news/detail-426457.html

到了這里,關于C++、STL標準模板庫和泛型編程 ——適配器、補充(侯捷)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • STL標準庫與泛型編程(侯捷)筆記6(完結)

    STL標準庫與泛型編程(侯捷)筆記6(完結)

    本文是學習筆記,僅供個人學習使用。如有侵權,請聯(lián)系刪除。 參考鏈接 Youbute: 侯捷-STL標準庫與泛型編程 B站: 侯捷 - STL Github:STL源碼剖析中源碼 https://github.com/SilverMaple/STLSourceCodeNote/tree/master Github:課程ppt和源碼 https://github.com/ZachL1/Bilibili-plus 下面是C++標準庫體系結構與內(nèi)核

    2024年01月16日
    瀏覽(15)
  • 31 C++ 模版和泛型

    我們先來看一類問題,如下的三個方法能否換成一個方法呢? 這就是模版的來歷。 所謂泛型編程,是以獨立于 任何 特定類型的方式編寫代碼 這意味著,我們在聲明或者定義的時候,不會指定具體的類型。 但是在使用的時候,需要指定具體的類型或者值 模版是泛型編程的基

    2024年02月02日
    瀏覽(18)
  • C++ STL 標準模板庫介紹與入門

    目錄 1、概述 1.1、C++ 標準庫 1.2、Boost庫 2、STL 版本 2.1、HP 原始版本

    2024年02月05日
    瀏覽(26)
  • c++標準模板(STL)(std::array)(三)

    c++標準模板(STL)(std::array)(三)

    template ? ? class T, ? ? std::size_t N struct array; (C++11 起 ? std::array 是封裝固定大小數(shù)組的容器。 此容器是一個聚合類型,其語義等同于保有一個 C 風格數(shù)組 T[N] 作為其唯一非靜態(tài)數(shù)據(jù)成員的結構體。不同于 C 風格數(shù)組,它不會自動退化成 T* 。它能作為聚合類型聚合初始化,只要

    2024年02月02日
    瀏覽(26)
  • 一天學完C++的標準模板庫STL

    一天學完C++的標準模板庫STL

    提到字符串,我們會想起C語言中的 char * ,這是一個指針。而在STL中 string 也是用來聲明字符串的,但是 string 是一個類,需要導入庫 #includestring 。 String 封裝了 char * ,管理這個字符串,是一個 char* 型的 容器 。 string 本質上是一個動態(tài)的 char 數(shù)組。 使用String字符串的第一步

    2023年04月17日
    瀏覽(17)
  • C++——STL標準模板庫——容器詳解——list

    C++——STL標準模板庫——容器詳解——list

    list:雙向鏈表。list是一種分布式存儲的線性表,每個節(jié)點分為數(shù)據(jù)域和指針域,其中指針域中包含一個指向前驅節(jié)點的指針和一個指向后續(xù)節(jié)點的指針,基本模型如下: 1、雙向鏈表:每個元素都有一個前驅和一個后繼,這種結構允許在鏈表的任何位置實現(xiàn)快速的插入和刪除

    2024年01月16日
    瀏覽(21)
  • 【C++】:STL——標準模板庫介紹 || string類

    【C++】:STL——標準模板庫介紹 || string類

    STL(standard template libaray-標準模板庫):是C++標準庫的重要組成部分,不僅是一個可復用的組件庫,而且 是一個包羅數(shù)據(jù)結構與算法的軟件框架 原始版本 Alexander Stepanov、Meng Lee 在惠普實驗室完成的原始版本,本著開源精神,他們聲明允許任何人任意運用、拷貝、修改、傳播、商

    2024年02月05日
    瀏覽(20)
  • 【C++】——模板(泛型編程+函數(shù)模板+類模板)

    【C++】——模板(泛型編程+函數(shù)模板+類模板)

    之前我們學習了函數(shù)重載,讓我們在寫相似函數(shù)的時候非常方便,但函數(shù)重載還有很多不足的地方,比如,每次寫相似函數(shù)的時候,都要我們重新重載一個邏輯、代碼幾乎一樣的函數(shù),這就導致了我們的效率變低,所以我們今天來學習C++模板的相關知識點,學習完模板之后,

    2024年02月05日
    瀏覽(25)
  • c++ 11標準模板(STL) std::vector (二)

    c++ 11標準模板(STL) std::vector (二)

    template ? ? class T, ? ? class Allocator = std::allocatorT class vector; (1) namespace pmr { ? ? template class T ? ? using vector = std::vectorT, std::pmr::polymorphic_allocatorT; } (2) (C++17 起) 1) std::vector 是封裝動態(tài)數(shù)組的順序容器。 2) std::pmr::vector 是使用多態(tài)分配器的模板別名。 元素相繼存儲,這意味著不

    2024年02月02日
    瀏覽(17)
  • (AI創(chuàng)作實驗)C++中的STL(標準模板庫)

    STL概述 STL: (Standard Template Library) 標準模板庫 包含一些常用的算法如排序查找,還有常用的數(shù)據(jù)結構如可變長數(shù)組、鏈表、字典等。 使用方便,效率較高 要使用其中的算法,需要#include C++中的STL(標準模板庫)是一個非常強大的工具,為程序員提供了許多高效的數(shù)據(jù)結構和算

    2023年04月18日
    瀏覽(22)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包