<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      • C++中除了面向對象的編程思想外,還有另一種就是泛型編程

      • 主要用到的技術就是模板

      模板機制的分類:

      • 函數模板

      • 類模板

      函數模板

      作用:建立一個通用函數,其函數返回值類型和形參類型可以不具體定制,用虛擬的類型來表示

      關鍵字:template

      語法:

      template <typename T> // template <class T>

      函數聲明或者定義

      • template:聲明創建模板

      • typename:表明后面的符號是一種數據類型,也可以用class代替

      • T:通用的數據類型,名稱可以替換,通常為大寫字母

      意義:將類型參數化,提高代碼通用性。

      使用方法:

      • 自動類型推導

      • 顯示指定類型

      注意事項:

      • 自動類型推導,無論有幾個 T,其必須要推導出一致的數據類型,才可以使用

      • 函數模板必須要確定 T 的數據類型,才可以使用

      與普通函數的區別:

      • 普通函數調用時可以發生自動類型轉換,也就是隱式轉換

      • 函數模板只有在調用顯示指定類型才會發生隱式轉換,用自動類型推導就不會

      示例:

      void SwapDouble(double &a, double &b)        //這是一個普通的兩個double類型數值交換的函數,缺點是數據類型被固定死了
      {
          double temp = a;
          a = b;
          b = temp;
      }
      
      template<typename T>                         //聲明一個函數模板,T是通用的數據類型
      void mySwap(T &a, T &b)
      {
          T temp = a;
          a = b;
          b = temp;
      }
      
      template<class T>
      void func()
      {
        cout << "注意事項"  << endl;
      }
      
      
      int main()
      {
          int a = 20;
          int b = 10;
          char c = '5';
          
         //1、自動推導類型,又編譯器自動推導出數據類型
          mySwap(a , b);
      
          //mySwap(a , c);    //×,因為 T 的數據類型不一致,一個是int型,一個是char型
                              // 同時自動推導類型不會發生隱式轉換,無法將int變char型,也無法將char變int型
      
         //2、顯示指定類型,直接告訴編譯器這兩個傳參的數據類型
          mySwap<int>(a , b)
      
         //func();           //×,因為 T 沒有一個確定的數據類型
           func<int>();      //√,因為我們給 T 指定了一個確定的數據類型
                             // 同時顯示指定類型可以發生隱式轉換,強制轉換為int型
      
      }

      調用規則

      • 如果普通函數和函數模板都實現了,優先使用普通函數

      • 可以通過空模板參數列表強制調用函數模板

      • 函數模板可以以發生函數重載

      • 如果函數模板可以更好的匹配,那肯定是優先使用函數模板啦

      示例:

      void Print(int a , int b)
      {
          cout << "普通函數" << endl;
      }
      
      template<class T>
      void Print(T a , T b)
      {
          cout << "函數模板" << endl;
      }
      
      template<class T>
      void Print(T a , T b , T c)
      {
          cout << "函數模板" << endl;
      }
      
      
      int main()
      {
          int a = 10;
          int b = 5;
          char c1 = 'a';
          char c2 = 'b';
      
          Print(a , b);          //1、普通函數和函數模板你都一樣實現的情況下,優先調用普通函數
      
          Print<>(a , b);        //2、利用空模板參數列表來強制調用函數模板
          Print<>(a , b , c);    //3、函數模板可以發生函數重載
          
         Print(c1 , c2);         //4、函數模板可以更好的匹配,優先調用函數模板
                                 //這是編譯器所做的決定,它覺得直接將類型變成通用類型 比 將char轉換成int更加方便
       }

      函數模板的局限性

      一些特定的數據類型,函數模板就處理不了

      示例:

      template<class T>
      void func(T a , T b)         //如果a 和 b 都是數組類型,那賦值操作就運行不了
      {                            //如果 T 是某一個類自定義數據類型,也處理不了
           a  = b;
      }
      • 為了解決這些問題,C++提供了模板的重載,為特定的數據類型提供具體化的模板

      • 利用具體化的模板,可以解決類型自定義的通用性

      • 但是模板其實不用去寫,可以在STL中調用系統提供的模板

      語法:

      template<> 返回值類型 函數名(參數1,參數2,···)

      示例:

      class Person
      {
      public:
          Person(string name ,int age)
          {
              this ->m_name = name;
              this ->m_age = age;
          }
          string m_name;
          int m_age;
      };
      
      template<class T>
      bool Compare(T &a , T &b)        //只能對比一些普通的變量,對于自定義的數據類型,無法處理
      {
         if(a == b)
             return ture;
         else
             return flase;
      }
      
      //template<>  表示這是個具體化Person實現的函數模板
      template<> bool Compare(Person &a , Person &b)
      {
          if(a.m_name == b.m_name && a.m_age == b.m_age)
              return ture;
          else
              return flase;
      }
      
      int main()
      {
          Person p1("張三",20);
          Person P2("李四",30);
          
          if(Conpare(p1 , p2))                   //只要參數是Person類型,編譯器會自動調用具體化Person類型的函數模板
              cout << "完全一致" << endl;
          else
              cout << "對比失敗" << endl;
      }

      類模板

      作用:建立一個通用的類,但是類中的成員變量類型未知,用一個虛擬的類型來表示

      語法:

      template<typename T> 類

      • template:聲明創建一個模板

      • typename:表明后面的 T 是一種數據類型,typename 也可以用class替代

      • T:通用的數據類型

      與函數模板的區別:

      • 類模板在使用的時候,沒有自動類型推導的方式

      • 類模板在模板參數列表中可以有默認參數類型

      示例:

      //temolate<class Nametype, class AgeType = int>     //類模板的參數列表可以說有默認參數類型
      template<class NameType, class AgeType>     //因為會有涉及到兩個不同類型的變量,所以創建了兩個虛擬的類型
      class Person
      {
      public:
          Person(NameType name, AgeType age)
          { 
              this->m_name = name;
              this->m_age = age;
          }
          NameType m_name;
          AgeType m_age;
      }
      int main()
      {
          Person<string ,int> p1("張三",99);        //既然指定了string類型,記得添加string頭文件
          // Person("李四",56);                     //×,類模板沒有自動類型推導的方式
          // Person<string> p2("王五",66);          //√,只要在前面有模板參數列表的聲明中默認參數就可以用
      }

      類模板成員函數創建時機

      • 普通類中的成員函數,在一可以就可以創建

      • 類模板中的成員函數,在函數調用時才創建

      示例:

      class Person1
      {
      public:
          void showPerson1(){   cout << "show Person1" << endl;  }
      }
      
      class Person2
      {
      public:
          void showPerson2() {   cout << "show Person2" << endl;  }
      }
      
      template<class T>
      class myClass
      {
      public:
           T obj;
           void func1(){  obj.showPerson1(); }   //因為是類模板,函數此時其實還沒有創建,所以隨便用別人家的函數也沒事
           void func2(){  obj.showPerson2(); }
      } 
      
      int main()
      {
          myClass<Person1> p1;                  // 將通用類型指定為 Person1 類型,創建了類 p1
          p1.func1();                           //此時才是創建成員函數 func1() 的時候,調用的時候才進行聲明
          //p1.func2();                         //因為指定的是 Person1 類,所以只有 Person1類中的 showPerson1()函數被聲明了
                                                //Person2 類中的 showPerson2() 并沒有被聲明,說明不能調用
      
          myClass<Person2> p2;
          //p2.func1();
          p2.func2();
      }

      類模板對象做函數參數

      作用:用模板實例出的對象來當做函數參數傳入

      傳入方式:

      • 指定傳入的類型:直接顯示對象的數據類型

      • 參數模板化:將對象中的參數變為模板進行傳遞

      • 整個類模板化:將整個對象進行模板化,傳遞下去

      一般而言第一種傳遞方式比較常見;

      第二種和第三種,其實有點像函數模板和類模板結合使用;

      使用函數 typeid(temp) 可獲知一個參數 temp 的類型;

      示例:

      template<class T1, class T2>
      class Person
      {
          Person(T1 name, T2 age)
          {
              this->m_name = name;
              this->m_age = age;
          }
          showPerson()
          {
              cout << "名字:" << this->m_name <<"年齡: " << this->m_age << endl;
          }
          T1 m_name;
          T2 m_age;
      }
      
      void func1( Person<string, int>&p )               //1、指定傳入類型
      {
          p.showPerson();
      }
      
      template<class T1, class T2>                     //要加上這個,不然編譯器不知道 T1 和 T2 是什么
      void func2( Person<T1, T2>&p );                  //2、參數模塊化,T1 和 T2 由編譯器根據傳參去推導
      {
          p.showPerson();
          cout << T1 的數據類型 << typeid(T1).name << endl;    //使用typeid()可獲知 T1 / T2 的數據類型
          cout << T2 的數據類型 << typeid(T2).name << endl;
      }
      
      template<classs T>
      void func3(T &p)                               //3、整個類進行模板化,T 由編譯器根據傳參去推導
      {
          p.showPerson();             
          cout << "T 的數據類型 " << typeid(T).name << endl;     //獲取 T 的數據類型      
      }
      
      int main()
      {
          Person<string , int> p("張三", 50);
          
          func1(p);                //1、指定傳入類型
          func2(p);                //2、參數模板化
          func3(p);                //3、整個類進行模板化
          
      }

      類模板與繼承

      當類模板碰到繼承時:

      • 當子類繼承的父類是一個類模板時,子類在聲明時要指定父類 T 的類型

      • 如果不指定,編譯器就無法給子類分配內存

      • 要想靈活指定父類中 T 的類型,子類也必須為類模板

      語法:

      template<class T1 , class T2>

      class 子類:繼承方式 父類<T2>

      {

      //T1 通用類型留給子類自己用

      }

      示例:

      template<class T>
      class Base
      {
          T m;
      }
      
      // class Son : public Base         //×,父類是類模板,繼承中需要指定父類中 T 的類型
      class Son1 : public Base <int>     //將父類中的數據類型指定為 int 型,這樣繼承才可以成功
      {
      }
      
      template<class T1, class T2>
      class Son2:public Base<T2>         //這樣 類模板的 Son2 的參數 T2 就變成了父類的 T 的類型,達到靈活指定父類 T類型的目的
      {                            
         T1 m;
      }
      
      int main ()
      {
         Son1 s1;                        //創建子類對象s1的時候,父類中的 T 類型就被強制指定成 int 型
         Son2 <char , int>s2;            //創建子類對象s2的時候,父類中的 T 類型就隨著子類的定義而改變,此時 父類中 T 便是 int 型
      }

      類模板成員函數的類外實現

      類外實現的方法:

      • 類內聲明,類外寫函數定義

      • 類外寫函數時,作用域需要加上模板參數列表

      語法:

      template<class T>

      返回值類型 作用域<T>::成員函數()

      //作用域要加上模板參數列表<T>,不管傳參和函數內部有沒有用到 T ,<T> 都要寫出來

      {

      }

      示例:

      template <class T1, class T2>
      class Person
      {
      public:
          //Person(T1 name , T2 age)                        //這是成員函數之構造函數的類內實現   
          // { 
          //     this->m_name = name;                  
          //     this->m_age = age;
          // }       
          // void PrintPerson()                             //這是成員函數之普通函數的類內實現
          // {
          //      cout << "姓名:" << this->m_name << "年齡" << this->m_age << endl;
          // }
      
            Person(T1 name, T2 age);                       //類外實現之類內聲明
            void PrintPerson();
      
          T1 m_name;
          T2 m_age;
      }
      
      template<class T1, class T2>
      Person<T1, T2>::Person(T1 name ,T2 age)
      {
          this->m_name = name;
          this->m_age = age;
      }
      
      template<class T1, class T2>
      void Person<T1 , T2>::PrintPerson()
      {
          cout << "姓名:" << this->m_name << "年齡" << this->m_age << endl;
      
      } 
      int main()
      {
          Person<string ,int> p("張三" , 50);
          p.PrintPerson();
      }

      分文件編寫

      在使用類模板過程中,進行分文件編寫會出現一些問題:

      一般的分文件編寫:

      .h:寫類聲明和成員函數定義

      .cpp:寫類中成員函數的實現

      x.cpp:寫主函數和應用功能

      原因:類模板的成員函數在主函數調用的時候才創建,所以會導致預處理時鏈接不到

      解決辦法(建議用第二種):

      1. 直接包含.cpp源文件(將x.cpp中的#include".h">改成#include".cpp",而.cpp中也有包含頭文件,這樣改,就是在跑主函數之前,將聲明和實現都跑了一遍)

      2. 將聲明和實現寫在同一個文件中,后綴名改成.hpp(.hpp是約定俗成的名字,不是強制的,但大家都這么寫)

      兩種方法,目的都是在跑主函數之前,將聲明和實現都先跑了一遍。

      類模板與友元

      類模板和友元配合成的全局函數的類內實現和類外實現:

      • 類內實現:直接在類內聲明友元即可(建議這個,比較簡單)

      • 類外實現:需要提前讓編譯器知道全局函數的存在(有點復雜,不建議)

      示例:

      template<class T1, class T2>                        //類外實現——這部分最好寫在最前面,提前讓編譯器知道這個Person類的存在
      class Person;
      
      template<class T1, class T2>                        //類外實現——這部分實現最好寫在前面,提前讓編譯器知道這個函數的存在
      void PrintPerson2( Person<T1, T2>p)
      {
          cout << "姓名:" << p.m_name << "年齡" << p.m_age << endl;
      }
      
      template<class T1, class T2>
      class person
      {
          friend void PrintPerson1( Person<T1,T2> p)                //全局函數,友元函數的類內實現,這個比較簡單
          {
             cout << "姓名:" << p.m_name << "年齡" << p.m_age << endl;
          }
         
         friend void PrintPerson2<>( Person<T1, T2> p);               //全局函數,友元函數的類外實現,需要先類內聲明,類外實現
                                                                      //加一個空模板參數列表,將這個普通函數變成類模板函數 
      public:
          Person(T1 name, T2 age)
          {
              this->m_name = name;
              this->m_age = age;
          }
      private:
          T1 m_name;
          T2 m_age;
      }
      
      int main()
      {
         Person<string, int> p("張三", 50);
         PrintPerson1(p);                   //類內實現
         PrintPerson2(p);                   //類外實現
       }

      STL

      • 之所以有C++的面向對象和泛型編程,目的就是提升可重復性

      • STL的誕生,就是為了建立一套數據結構和算法的標準,提高可重復利用性

      STL基本概念

      • STL,即標準模板庫

      • 從廣義上分為:容器、算法、迭代器

      • 從細分上分為:容器、算法、迭代器、仿函數、適配器(配接器)、空間配置器

      • 容器和算法通過迭代器進行無縫連接

      • STL所有的代碼都運用到了函數模板和類模板

      STL六大組件

      六大組件就是上線說到的:容器、算法、迭代器、仿函數、適配器(配接器)、空間配置器

      • 容器:各種數據結構,如vector、list、deque、set、map等,用來存放數據

      • 算法:各種常用算法,如sort、find、copy、for_each等

      • 迭代器:容器和算法之間的鏈接器

      • 仿函數:類似函數,可作為算法的某種策略

      • 適配器:一種用來修飾容器或者仿函數或者迭代器的東西

      • 空間配置器:負責空間的分配和管理

      容器

      作用:存放數據,將廣泛使用的數據結構給實現出來

      常用的數據結構:數組、鏈表、樹、棧、隊列、集合、映射表等

      容器的分類:

      • 序列式容器:強調值的位置,每個元素都有固定的位置

      • 關聯式容器:二叉樹結構,元素之間沒有嚴格的物理上的順序關系

      算法

      作用:問題的解法,即用有限的步驟,解決邏輯上的難題

      算法的分類:

      • 質變算法:運算中更改區間內元素的內容,如拷貝、替換、刪除等

      • 非質變算法:運算中不會更改區間內元素的內容,如查找、計數、遍歷、尋值等

      迭代器

      作用:容器和算法之間的鏈接器,即就是提供一種方法,既能依序尋找容器內某個元素,又不暴露容器內部的表示方法

      • 每個容器都有自己專屬的迭代器

      • 迭代器的使用方法類似于指針

      • 最常用的是雙向迭代器和隨機訪問迭代器

      迭代器的種類:

      種類

      功能

      支持運算

      輸入迭代器

      對數據的只讀訪問

      只讀,支持++、==、!=

      輸出迭代器

      對數據的只寫訪問

      只寫,支持++

      前向迭代器

      對數據的向前操作

      讀寫,支持++、==、!=

      雙向迭代器

      對數據的向前和向后操作

      讀寫,支持++、--

      隨機訪問迭代器

      訪問任何數據,功能最強

      讀寫,支持++、--、[n]、-n、<、<=、>、>=

      String容器

      基本概念

      • string是C++風格的字符串,但是本質上是一個類

      • String是內部封裝了char類型,管理string這個類,用的是char*的容器

      • 包含頭文件#include<string>

      特點

      • string內部封裝了很多成員函數方法,比如find查找,copy復制,delete刪除,replace替換,insert插入等等

      • string管理char*所分配出來的內存,不用擔心復制越界內存和取值越界,也不用擔心溢出或者碎片,這些由容器內部統一管理

      string構造函數

      • string();無參構造,主要用來創建一個空字符串

      • string(const char* s); 用來初始化一個字符串

      • string(const string& str); 用一個string對象來初始化另一個string對象

      • string(int n,char c); 初始化n個字符c

      • 以上構造函數沒有什么可比性,根據實際情況靈活運用即可

      示例:

      #include<string>     //只要涉及到string,就要包含其頭文件
      int main()
      {
          string s1;                      //1、用于創建一個空的字符串
      
          const char* str = "中秋節";
          string s2(str);                 //2、創建一個字符串s2,將字符串s1初始化賦值給字符串s2
          cout << "str2 = " << s2 << endl;
      
          string s3(s2);                  // 調用拷貝構函數
          cout << "str3 = " << s3 << endl;
      
         string s4(10,'A');              //3、創建一個字符串4,初始化賦值為10個‘A’
         cout << "str4 = " << s4 << endl;
      }

      賦值操作

      作用:給string字符串賦值

      函數原型:

      • string& operator= ( const char *s ) ; 將char *類型的字符串賦值給當前字符串

      • string& operator= ( const string &s ) ; 將string類型字符串賦值給當前字符串

      • string& operator= ( char c ) ; 將字符c賦值給當前字符串

      • string& assign ( const char*s ) ; 將char *類型字符串賦值給當前字符串

      • string& assign ( const char *s, int n ) ; 將char *類型的字符串的前n個字符賦值給當前字符串

      • string& assign ( const string &s ) ; 將const類型的字符串賦值給當前字符串

      • string& assign ( int n,char s ) ; 將n個字符s賦值給當前字符串

      示例:

      int main()
      {
           string s1;
           s1 = "hello C++";          //相當于operator=("hello C++"),由編譯器進行內部轉化
           cout << "s1 = " << s1 << endl;
      
           string s2;
           s2 = s1;                    //相當于operator=(s1),由編譯器進行內部轉化
           cout << "s2 = " << s2 << endl;
      
           string s3;
           s3 = 'A';                  //相當于operator=('A'),由編譯器進行內部轉化
           cout << "s3 = " << s3 << endl;
      
           string s4;
           s4.assign("Hello C++");     //也就是 string&  assign ( const char *s)
           cout << "s4 = " << s4 << endl;
      
           string s5;
           s5.assign(s4);             //也就是 string&  assign ( const string &s )
           cout << "s5 = " << s5 << endl;
      
           string s6;
           s6.assign("hello C++",5);  //也就是 string&  assign ( const char *s,int n)
           cout << "s6 = " << s6 << endl;
      
           string s7;
           s7.assign(10,'A');         //也就是 string&  assign ( int n, char s)
           cout << "s7 = " << s7 << endl;
      }

      字符串拼接

      作用:就是在字符串末尾再拼接一段字符串

      函數原型:

      • string& operator+ ( const char *c ) ; //將char*類型的字符串拼接到當前字符串末尾

      • string& operator+ ( const char c ) ; //將字符c拼接到當前字符串末尾

      • string& operator+ ( const string& str ) ; //將string類型的字符串拼接到當前字符串末尾

      • string& append ( const char *s ) ; //將char*類型的字符串拼接到當前字符串末尾

      • string& append ( const char *s , int n ); //將char*類型字符串的前n個字符拼接到當前字符串末尾

      • string& append ( const string &s ) ; // 將string類型額字符串拼接到當前字符串末尾

      • string& append ( const string &s, int pos , int n ); //將string類型的字符串從pos個開始的n個字符拼接到當前字符串末尾

      示例:

      int main()
      {
         string s1 = "I";
         s1 += "love games";               //相當于 string& operator+ ( const char *c ),由編譯器內部自動轉化
         cout << "s1 = " << s1 <<endl;     
      
         s1 += ';';                        //相當于 string& operator+ ( const char c ),由編譯器內部自動轉化
         cout << "s1 = " << s1 <<endl;
      
         string s2 = "LOL";
         s1 += s2;                         //相當于 string& operator+ ( const string& str ),由編譯器內部自動轉化
         cout << "s1 = " << s1 <<endl;
      
         string s3 = "I";
         s3.append(" love ");              //相當于 string& append ( const char *s ) ;
         s3.append("game abcsd ", 4);      //相當于 string& append ( const char *s ,int n) ;
         cout << "s3 = " << s3 <<endl;
      
         s3.append(s2);                    //相當于 string& append ( const string& s ) ;
         cout << "s3 = " << s3 <<endl;
      
         string s4 = "sjdia DNF";
         s3.append(s4, 5, 3);             //相當于 string& append ( const string &s, int pos , int n );
         cout << "s3 = " << s3 <<endl;
      }

      字符串的查找和替換

      作用:

      • 查找:查找指定的字符串是否存在

      • 替換:在指定的位置替換字符串

      函數原型:

      • int find ( const string& str , int pos = 0 ) const ; //查找str第一次出現的位置,從pos開始查找

      • int find ( const char* s , int pos = 0 ) const ; //查找 s 第一次出現的位置,從pos開始查找

      • int find ( const char* s ,int pos , int n ) const ; //查找s的前n個字符第一次出現的位置,從pos開始查找

      • int find ( const char c , int pos = 0 ) const ; //查找字符串 c 第一次出現的位置,從pos開始查找

      • int rfind ( const string& str , int pos = npos ) const; //查找str最后一次的位置,從pos開始查找

      • int rfind ( const char* s , int pos = npos ) const ; //查找 s 最后一次出現的位置,從pos開始查找

      • int rfind ( const char* s , int pos , int n) const; //查找 s 的前n個字符最后一次的位置,從pos開始查找

      • int rfind ( const char s , int pos = 0 ) const ; //查找字符 s 最后一次出現的位置,從pos開始查找

      • string& replace ( int pos , int n , const string& str) ; //從pos開始的n個字符,替換成字符串str

      • string& replace ( int pos , int n , const char* s); //從pos開始的n個字符,替換成字符串 s

      特點:

      • find是從左往右找,rfind是從右往左找,找到了返回下標位置,找不到返回 -1

      • replace會把替換字符串全部替換進去,不管你指定多少個字符

      示例:

      int main()
      {
          string s1 = "sdafaffgg";
          int ret = s1.find("fa");      //查找"fa"第一次出現的位置
          if( ret == -1 )
               return 0;
          
          ret = s1.rfind ("fa");         //查找"fa"最后一次出現的的位置
          if( ret == 1)
                return 0;
      
          s1.replace(2, 3, "AAAAA");     //將字符串s1的第2個開始的3個字符開始,全部替換成“AAAAA”
          
      }

      字符串比較

      作用:字符串之間的比較

      特點:

      • 以其中的字符的ASCII值得方式進行比較

      • > 返回 1

      • < 返回 -1

      • = 返回 0

      • 主要是用來比較兩個字符串是否一樣,比較大小沒有什么意義

      函數原型:

      • int compare ( const string& s) const ; //與string類型的字符串進行比較

      • int compare ( const char s ) const ; //與char*類型的字符串進行比較

      示例:

      int main()
      {
         string s1 = "dafwfw" ; 
         string s2 = "dasff" ; 
         if ( s1.compare( s2 ) == 0)
         {
             //主要是用來比較是否相等
         }
         else if (s1.compare(s2) > 0)
         {
         }
         else
         {
         }
      }

      字符存取

      對單個字符進行存取有兩種方法:

      • 通過 [ ] 方式進行存取

      • 通過at函數方式進行存取

      函數原型:

      • char& operator[](int n) ; //通過[]方式存取

      • char& at(int n); //通過at方式存取

      示例:

      int main()
      {
         string s1 = "hello C++";
         
         for(int i = 0 ; i < s1.size(); i++)
         {
             cout << s1[i] << endl;             //通過 [] 方式讀取 
             cout << s1.at(i) << endl;          //通過 at 方式讀取
         }
         str[0] = 'H';                          //通過[]方式修改
         str.at(1) = 'E';                       //通過at方式修改
         cout << s1 << endl ;
      }

      字符的插入和刪除

      作用:對字符串中進行插入和刪除字符的操作

      函數原型:

      • string& insert ( int pos , const char* s ) ; //從pos位置開始插入字符

      • string& insert ( int pos , const string& s); //從pos位置開始插入字符

      • string& insert ( int pos , int n, char s); //從pos位置開始,插入n個字符s

      • string& erase( int pos , int n = npos ) ; //從pos位置開始,刪除n個字符

      • 參數pos的位置,都是從下標0開始的

      示例:

      int main()
      {
           string s1 = "hello" ; 
           s1.insert(1 , "aaaa");     //從下標1位置開始,插入字符串“aaaa”
           cout << s1 << endl;
      
           s1.erase( 1, 4 );         //從下標1位置開始,刪除4個字符
           cout << s1 << endl;
      
           system("pause");
           return 0;
      }

      字符串子串

      作用:從字符串中截取想要的子串

      函數原型:

      • string substr( int pos , int n = npos) const ; //從pos位置開始,截取n個字符

      示例:

      int main()
      {
         string s1 = "safagrgwg";
         string substr = s1.substr( 0 , 3 );     //從s1字符串中,從位置0開始,截取3個字符作為子串
         cout  << substr << end;
      
         system("pause");
         rerurn ;
      }

      Vector容器

      基本概念

      • vector數據結構與數組非常相似,但是只能進行尾部的插入和刪除,所以也被稱為單端數組

      • vector容器的迭代器是支持隨機訪問的迭代器,功能最強大的迭代器之一

      • 包含頭文件 #include<vector>

      與普通數組的區別

      • 數組是靜態空間

      • vector可以動態擴展

      • 動態擴展并不是在原空間上續接新空間,而是尋找更大的空間,將原數據拷貝過去,在新空間后續接空間,釋放源空間

      ? ?vector容器結構以及成員函數 編輯

       

      構造函數

      作用:創建vector容器

      函數原型:

      • vector <T> v ; //默認構造函數,T 是數據類型 , v是容器名字

      • vector ( v.begin() , v.end() ) ; //將v.[ begin() , end() ) 區間中的元素拷貝給本身

      • vector ( n , a ) ; //構造函數將 n 個 a 數值拷貝給本身

      • vector ( const vector &ver ) ; //拷貝構造函數

      示例:

      int main()
      {
         vector <int> v1;                           //創建方法一:默認構造,無參構造
         for ( int i = 0; i< 10; i++)
         {
             v1.push_back(i);     //將0~9這些參數填入容器中
         }
      
         vector<int> v2 ( v1,begin(), v1.end());   //創建方法二:將v1容器中的數據拷貝給容器v2
         
         vector<int> v3( 10, 100 );                //創建方法三:將10個100填入容器v3
       
         vector<int> v4( v3 );                     //創建方法四:將v3容器數據拷貝給容器v4
      
          system("pause");
          return 0;
      }

      vector賦值

      作用:給vector容器進行賦值操作

      函數原型:

      • vector& operator= ( const vector &vst ) ; //重載方式進行賦值

      • assign ( begin , end ) ; //將 [ begin , end )區間內的數值賦值給本身

      • assign (n , A) ; //將n個字符A賦值給本身

      示例:

      int main()
      {
          vector<int> v1;
          for(int i = 0 ; i < 10; i++)
          {
               v1.push_back(i);
          }
          vector<int> v2;                                  //賦值方法一:重載賦值
           v2 = v1;
        
          vector<int> v3;
          v3.assign(v1,begin() , v1.end() );               //賦值方式二:將v1的區間[begin ,end) 數據賦值給v3
      
          vector<int> v4;
          v4.assign(10 , 200);                              //賦值方式三,將10個200賦值給v4
      }

      容量和大小

      作用:獲取vector容器的容量和大小參數

      函數原型:

      • empty ( ) ; //判斷是否為空

      • capacity ( ) ; //獲取容器的容量

      • size ( ) ; //獲取元素個數

      • resize ( int num ) ; //重新指定容器長度,容器變長,超出的用0表示;容器變短,超出的被刪除

      • resize ( int num,int elem ) ; //重新指定容器元素,容器變長,超出的用elem表示,變短則超出的被刪除

      示例:

      void PrintVector(vector<int>& v)                                 //利用迭代器寫出的打印容器函數
      {
          for(vector<int>::iterator i = v.begin();i < v.end(); i++)
          {
              cout << *i << " " ;
          }
          cout << endl;
      }
      int main()
      {
          vector<int> v;
          for( int i = 0;i < 10; i++)
              v.push_back(i);
          PrintVector(v);
          
          if( v.empty() )                                             //判斷容器是否為空
           {
                 cout << "容器v為空" << endl;
           }
           else
           {
                cout << " 容器v不為空" << endl;
                cout << "容器v的容量為:" << v.capacity() << endl;   //獲取容器的容量
                cout << "容器v的大小為:" << v.size() << endl;       //獲取容器的元素個數
           }
      
            v.resize( 15 , 100);                                      //重新指定容器長度
                                                                      //如果超出容器本身長度,超出的用100表示
                                                                      //如果比容器本身小,多余的會被刪除
            PrintVector(v);
       
            v.resize ( 5 );                                          //重新指定容器長度
                                                                     //如果超出容器本身長度,超出的默認0表示
                                                                     //如果比容器本身小,多余的會被刪除
            PrintVector(v);
      }

      插入和刪除

      作用:在容器中插入元素和刪除元素

      函數原型:

      • push_back ( ) ; //尾部插入

      • pop_back ( ) ; //刪除尾部最后一個元素

      • insert ( const_iterator pos , elem ) ; //插入元素elem,第一個參數是迭代器指向位置

      • insert (const_iterator pos , int num , elem ) ; //插入num個elem數值,第一個參數是迭代器指向位置

      • erase ( const_iterator pos ); //刪除元素,第一個參數是迭代器指向位置

      • erase ( const_iterator begin , const_iterator end ); //刪除從頭到尾的元素

      • clear ( ); //刪除容器內全部元素

      示例:

      void PrintVector( vector<int>& v)                    //一個打印函數,用于打印容器內的數據
      {
          for( vector<int>::iterator i = v.begin(); i<v.end(); i++)
          {
                 cout << "*i" << " " ;
           }
           cout << endl;                  
      }
      
      int main()
      {
          vector<int> v;
         
          for(int i=0;i<10;i++)
               v.push_back( i );                //尾部插入0~9元素
          PrintVector(v);
      
          v.pop_back();                         //刪除最后一個元素
          PrintVector(v);
         
          v.insert(v.begin() , 100);           //在迭代器begin位置插入元素100
          PrintVector(v);
         
          v.insert( v.begin() , 3, 100 );      //在迭代器begin位置插入3個元素100
          PrintVector(v);
       
          v.erase( v.begin() );                //產出迭代器begin位置的元素
          PrintVector(v);
      
          v.erase( v.begin() , v.end() );      //產出迭代器從begin到end之間的元素
          PrintVector(v);
          
          v.clear();                           //刪除容器內全部元素
          PrintVector(v);
      
          system("pause");
          return 0;
      }

      數據存取

      作用:獲取容器中的數據

      函數原型:

      • at ( int idx ) ; //返回索引下的元素

      • operator[ ] ; //重載方式返回索引下的元素

      • front ( ) ; //獲取容器第一個元素

      • back ( ) ; //獲取容器中最后一個元素

      示例:

      int main()
      {
          vector<int> v;
          for(int i = 0; i< 10; i++)
          {
                v.push_back ( i ) ;                               //開始填充容器元素
          }
          for(i = 0; i< 10; i++)
                 cout << v[i] << " ";                             //以重載方式operator[]獲取容器元素
          cout << endl;
          
          for(i = 0;i < 10; i++)
                 cout << v.at(i) << " ";                          //以at()方式獲取容器元素
          cout << endl;
         
          cout << "容器v的的第一個元素:" << v.front() << endl;   //獲取第一個元素v.front()
          cout << "容器v的最后一個元素:" << v.back() << endl;    //獲取最后一個元素v.back()
      }

      容器互換

      作用1:實現兩個容器之間的元素互換

      作用2:用于收縮容器容量(原理就是創建一個小容量的容器與本身的大容量容器互換)

      函數原型:

      • swap( vec ) ; //將容器vec中的元素與本身互換

      示例:

      void PrintVector( vector<int>& v )
      {
          for(vectot<int>::iterator it = v.begin(); it < v.end(); it++)
          {
               cout << *it << " ";
          }
          cout << endl;
      }
      int main()
      {
          //==========================作用1:容器元素互換========================================//
          vector<int> v1;
          for(int i = 0 ; i< 10 ; i++)
              v1.push_back(i);
      
          vector<int> v2;
          for(int i = 10; i > 0; i--)
              v2.push_back(i);
      
          PrintVector(v1);               //元素互換之前
          PrintVector(v2);
         
          v1.swap ( v2 ) ;
         
          PrintVector(v1);               //元素互換之后   
          PrintVector(v2);
      
         //==============================作用2:收縮容器內存============================================//
         
         vector<int> v;
         for(int i = 0; i < 10000; i++)                             //創建一個容器,里面有10000個元素
              v.push_back(i);
      
        cout << "此時容器大小為:" << v.size() << endl;             //此時大小 = 10000
        cout << "此時容器的容量為:" << v.capacity() << endl;       //此時容量 > 10000
      
        v.resize(3);                                               //重新指定容器大小 = 3
      
        cout << "此時容器大小為:" << v.size() << endl;            //此時大小 = 3
        cout << "此時容器的容量為:" << v.capacity() << endl;      //但是此時容量依舊是 > 10000,這就很浪費內存
                
        vector<int> v.swap ( v ) ;                                 //以v為拷貝,創建一個匿名對象x,此時x大小和容量 = 3
                                                                   //將容器x 與 容器v進行互換
                                                                   //容器x變成了容器v,此時x的大小 = 3,,容量 > 10000  
                                                                   //容器v就換成了容器x,此時v就變成大小和容量 = 3
                                                                   //而容器x由于是匿名對象,執行完其內存就后就被系統釋放掉了 
      
        cout << "此時容器的容量為:" << v.capacity() << endl;      //此時容器v的容量 = 3
        cout << "此時容器大小為:" << v.size() << endl;            //此時容器的大小 = 3
         
      }

      預留內存

      作用:在一開始就開辟出足夠的空間,減少動態擴展的次數

      原理:因為一旦容器輸入數據量較大的時候,編譯器會根據內存實際情況時不時進行動態擴展,動態擴展次數一旦多了,操作時間就長了,所以最好是在一開始就預留足夠多的空間,將動態擴展次數維持為1次。

      函數原型:

      • reserve ( int len ) ; //預留len個元素長度,預留位置不初始化,也不可以訪問

      示例:

      int main()
      {
         vector<int> v;
      
         v.reserve(10000);                        //從一開始就預留10000個元素大小的內存
      
         int num = 0;
         int *p = NULL:  
         for(int i = 0; i< 10000; i++)
         {
              v.push_back( i );
              if( p != &v[0])                     //以 指針p實時跟蹤容器首元素位置 來確定動態擴展次數
              {
                  p = &v[0];
                  num ++;
              }
         }
      
        cout << "動態擴展的次數:" << num << endl;
      }

      vector排序

      • 作用:利用算法對容器內元素進行排序

      • 需要包含算法頭文件 #include <algorithm>

      • 對于隨時訪問的迭代器都可以使用該排序函數

      函數原型:

      • sort( iterator begin , iterator end ) ; // 對begin和end之間的元素進行從小到大排序

      示例:

      void PrintVector( const vector<int>& dv)
      {
          for( vector<int>::const_iterator it = d.begin(); it != d.end(); it++ )
          {
              cout << *it << " ";
          }
          cout << endl;
      }
      int main()
      {
           vector<int> d;
           d.push_back(10);
           d.push_back(30);
           d.push_back(20);
           d.push_back(100);
           d.push_back(50);
           d.push_back(70);
           Printvector(d);                      //排序前
         
           sort( d.begin(), d.end() );         //進行排序
           Printvector(d);                      //排序后
        
           system("pause");
           return 0;
      }

      deque容器

      • 與數組類似,可以進行頭部和尾部的插入和刪除,因為也被稱為雙端容器

      • deque容器的迭代器也是支持隨機訪問的

      • 頭文件#include <deque>

      deque與vector的區別:

      • vector容器只能尾部插入和刪除,因為對于頭部操作效率很低,數據量越大越低

      • deque容器頭部的插入和刪除速度比vector快多了

      • vector和deque內部結構不同,導致元素的速度vector會更快,導致deque沒有容量限制,可以無限擴張

      • 二者的迭代器都支持隨機訪問,是最強大的迭代器之一

      ? deque內部結構和成員函數 編輯

      ?

      內部工作原理

      • deque內部有一個中控器,用于記錄每段緩沖區的地址,緩沖區中放置真實數據

      • 中控器+緩沖區,使得deque看起來像是一塊連續的內存

      ? deque內部工作原理 編輯

      ?

      構造函數

      作用:創建deque容器

      函數原型:

      • deque<T> d ; //默認構造函數,T表示數據類型

      • deque( begin , end ) ; //將容器[ begin , end )區間內的數據拷貝給本身

      • deque( count , elem ) ; //將count個elem數值拷貝給本身

      • deque ( const deque& d ) ; //拷貝構造函數,將容器數據整個拷貝給本身

      示例:

      void PrintDeque( const deque<int>& d )                                //為了放置d容器被中間意外修改,最后增加const修飾
      {
          for(deque<int>::const_iterator i = d.begin(); i != d.end(); i++)  //迭代器就得使用const修飾的迭代器
          {
               cout << *i << " ";
          }
          cout << endl;
      }
      int main()
      {
          deque<int> d1;                                  //構造方法一:無參構造
          for( int i = 0; i < 10 ; i++)
          {
               d1.push_back(i);
          }
           PrintDeque(d1);
           
          deque<int> d2( d1.begin() , d1.end() );       //構造方法二:將d1的[begin() , end()) 區間之內的數據拷貝給容器d2
          PrintDeque(d2);
      
          deque<int> d3(10 , 200);                      //構造方式三:將10 個 200 拷貝給容器d3
          PrintDeque(d3);
      
          deque<int> d4 (d1);                           //構造方式四:將d1容器整個拷貝給d4
          PrintDeque(d4);
      
          system("pause");
          return 0;
      }

      賦值操作

      作用:給deque容器進行賦值

      函數原型:

      • deque& operator=( const deque& d) ; //重載方式進行賦值

      • assign ( begin , end ); //將[ begin , end )區間內的數據賦值給容器

      • assign ( count , elem ); //將count個elem數值賦值給容器

      示例:

      void PrintDeque ( const deque<int>& d )
      {
          for( deque<int>::const_iterator it = d.begin(); it != d.end(); it++ )
          {
              cout << *it << " " ;
          }
          cout << endl;
      }
      int main()
      {
          deque<int> d1;
          for(int i = 0; i< 10; i++)
             d1.push_back( i );
          PrintDeque(d1);
      
          deque<int> d2;
          d2 = d1;                                 //賦值方式一:重載方式
          PrintDeque(d2);
         
         deque<int> d3;
         d3.assign( d1.begin() , d1.end() );      //賦值方式二:將d1的[ begin , end )之間數據賦值給d3
         PrintDeque(d3);
      
         deque<int> d4;
         d4.assign( 10 , 200);                   //賦值方式三:將10個200賦值給容器d4
         PrintDeque(d4);
      
         system("pause");
         return 0;
      }

      獲取大小,沒有容量限制

      • 作用:獲取deque內部的元素長度

      • 由于中控器+緩沖區的內部結構,導致deque是沒有容量限制的,理論上內存可以無限擴張,所以沒有獲取容量的函數

      函數原型:

      • empty( ) ; // 判斷容器是否為空

      • size( ) ; //獲取元素個數

      • resize ( num ) ; //重新指定容器長度,若容器變長,以默認值0填充新位置;若長度變短,超出部分刪除

      • resize ( num , elem ) ; //重新指定容器長度,若容器變長,以elem填充新位置,若變短,超出部分刪除

      示例:

      void PrintfDeque(const deque<int>& d)
      {
          for( deque<int>::const_iterator i = d.begin(); i != d.end(); i++ )
          {
              cout << *i << " " ;
          } 
          cout << endl;
      }
      int main()
      {
          deque<int> d;
          for(int i = 0; i < 10 ; i++ )
               d.push_back(i);
      
          if ( d.empty() )
          {
               cout << "容器d為空:" << endl;
          }
          else
          {
               cout << "容器d不為空:" << endl;
               PrintfDeque(d);
               cout << "容器d的長度為:" << d.size() << endl;
          }
          d.resize( 5 );
          PrintDeque(d);
          
          d.resize(10 ,100);
          PrintfDeque(d);
       
          system("pause");
          return 0;
      }

      插入和刪除

      作用:在容器兩端進行插入和刪除新數據

      函數原型:

      • push_back( elem); // 尾部插入數據elem

      • push_front( elem); //頭部插入數據elem

      • pop_back( ); //刪除最后一個元素

      • pop_front( ); //刪除第一個元素

      • insert( pos ,elem); //在迭代器位置pos插入數據elem

      • insert( pos , n, elem ); //在迭代器位置pos插入n個elem數據

      • insert( pos, begin, end ); //在迭代器位置pos插入[begin , end)區間內的數據

      • erase( pos); //刪除迭代器位置pos的數據

      • erase( begin , end ); //刪除從begin到end之間的數據

      • clear(); //刪除容器內所有元素

      示例:

      void PrintDeque( const deque<int>& d )
      {
          for( deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
                 cout << *it << " " ;
          cout << endl;
      }
      int main()
      {
           deque<int> d1;
           for(int i = 0; i< 10 ; i++)
               d1.push_back(i);                      //容器尾部添加數據
           PrintDeque(d1);
      
           d.push_front(100);                        //容器頭部插入100
           d.pop_back();                             //刪除最后一個元素
           d.pop_front();                            //刪除第一個元素
           PrintDeque(d1);  
      
           deque<int> d2;
           deqeu<int>::iterator i = d2.begin();      //用迭代器指定位置
           
           d2.insert(i , 100 );                     //在指定位置 i 插入100
           d2.insert(i+1 , 2, 50 );                 //在指定位置 i 插入2個50
           PrintDeque(d2);
      
           d2.insert(i , d1.begin(), d1.end() );      //在指定位置 i 插入d1的[begin , end )所有數據
           PrintDeque(d2);
      
           d2.earse(i);                              //刪除指定位置的元素
           d2.erase(d2.begin(), d2.end() );          //刪除從begin到end之間的元素
           d2.clear();                               //刪除容器內所有元素
           PrintDeque(d2);
      }

      數據存取

      作用:對deque容器中的數據進行存取

      函數原型:

      • operator[ ] ; //重載方式返回索引idx的數據

      • at( int dix ) ; //at()返回索引idx的數據

      • front( ) ; //返回第一個元素

      • at( ) ; //at()返回索引idx的數據

      示例:

      void PrintDeque( const deque<int>& d )
      {
         for( deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
             cout << *it << " ";
         cout << endl; 
      }
      int main()
      {
           deque<int> d;
           for(int i = 0;i< 10;i++ )
           {
                d.push_back(i);
           }
           for(i=0;i<10;i++)
               cout << d[i] << " ";                         //重載方式獲取容器元素
            cout << endl;
      
          for(i = 0;i<10;i++)
               cout << d.at(i) << " " ;                     //at()方式獲取容器元素
          cout <<endl;
      
          cout << "第一元素為:" << d.front() << endl;      //獲取第一個元素
          cout << "最后一個元素為:" << d.back() << endl;   //獲取最后一個元素
      
          system("pause");
          return 0;
      }

      deque排序

      • 作用:利用算法對容器內元素進行排序

      • 需要包含算法頭文件 #include <algorithm>

      • 對于隨時訪問的迭代器都可以使用該排序函數,包括vector容器

      函數原型:

      • sort( iterator begin , iterator end ) ; // 對begin和end之間的元素進行從小到大排序

      示例:

      void PrintDeque( const deque<int>& d )
      {
          for( deque<int>::const_iterator it = d.begin(); it != d.end(); it++ )
          {
              cout << *it << " ";
          }
          cout << endl;
      }
      int main()
      {
           deque<int> d;
           d.push_back(10);
           d.push_back(30);
           d.push_back(20);
           d.push_back(100);
           d.push_back(50);
           d.push_back(70);
           PrintDeque(d);                      //排序前
         
           sort( d.begin(), d.end() );         //進行排序
           PrintDeque(d);                      //排序后
        
           system("pause");
           return 0;
      }

      stack容器

      • stack容器是一種前進后出的數據結構,又稱為棧容器

      • 該容器只有頂端的元素才可以給外界獲取

      • 該容器不允許有遍歷行為

      • 包含頭文件 #include <stack>

      ? stack容器內部結構以及成員函數 編輯

      ?

      構造函數

      函數原型:

      • stack<T> stk ; //默認構造函數

      • stack( const stack &stk ) ; // 拷貝構造函數

      賦值操作

      函數原型:

      • stack& operator=( const stack& stk ) ; //重載方式進行賦值

      數據存取

      函數原型:

      • push( elem ) ; //向棧頂添加元素

      • pop( ) ; //刪除棧頂第一個元素

      • top( ) ; //返回棧頂元素

      大小獲取操作

      函數原型:

      • empty( ) ; //判斷容器是否為空

      • size( ) ; // 返回容器的大小

      示例:

      int main()
      {
          stack<int> stk;                                           //創建一個棧容器
         
          for(int i = 0; i< 10; i++ )
         {
             stk.push(i);                                           //往棧頂添加元素
         }
      
         while( !stk.empty() )                                       //判斷棧是否為空
         {
             cout << "棧頂的元素為:" << stk.top() << endl;          //返回棧頂元素
             cour << "棧的長度為:" << stk.size() << endl;           //返回棧的大小
             stk.pop();                                              //刪除棧頂元素
         }
      
          system("pause");
          return 0;
      }

      queue容器

      • queue容器是一種先進先出的數據結構,又稱為隊列容器

      • 允許從一段添加元素,另一端刪除元素

      • 只有隊尾和隊頭可以被外界使用,因此不允許有遍歷行為

      • 包含頭文件 #include<queue>

      ? queue內部結構和成員函數 編輯

       

      構造函數

      函數原型:

      • queue<T> que ; //默認構造函數

      • queue( const queue& que ) ; //拷貝構造函數

      賦值操作

      函數原型:

      • queue& operator=( const queue& que ) ; //重載方式賦值

      數據存取

      函數原型:

      • push( elem ) ; //往隊尾添加元素

      • pop( ) ; //刪除隊頭的元素

      • back( ) ; //返回最后一個元素

      • front( ) ; //返回第一個元素

      大小獲取

      函數原型:

      • empty( ) ; //判斷隊列是否為空

      • size( ) ; // 判斷隊列的大小

      示例;

      class Person()
      {
      public;
         Person(string name , int age)
         {
             this->m_name = name;
             this->m_age = age;
         }
          string m_name;
          int m_age;
      }
      int main()
      {
           queue<Person> q;
           
           Person p1("張三" ,10 );
           Person p2("李四" , 20 );
           Person p1("王五" ,30 );
           Person p1("趙六" ,40 );
      
          q.push(p1);
          q.push(p2);
          q.push(p3);
          q.push(p4);
      
          while( !empty() )
          {
              cout << "第一元素:"  << q.front() << endl;
              cout << "最后一個元素:"  << q.back() << endl;
              cout << "容器的長度:" << q.size() << endl;
              q.pop();
          }
      }

      list容器

      • list容器是一種雙向循環的數據結構,又稱為鏈式容器

      • 內部結構并不是連續的內存,迭代器不能隨訪問,只能前移和后移,屬于雙向迭代器

      • 包含頭文件 #include<list>

      • 動態存儲分配,不會存在內存浪費和溢出的問題

      • 隨機訪問,插入和刪除非常方便

      • 占用空間比較大,遍歷的消耗非常大

      ? list容器內部結構以及成員函數 編輯

       

      構造函數

      作用:創建一個list容器

      函數原型:

      • list<T> lst ; //默認構造函數

      • list( begin , end ) ; //將區間 [ begin ,end)之間的元素拷貝給本身

      • list( n , elem ) ; // 將 n個elem拷貝給本身

      • list( const list &lst) ; // 拷貝構造函數

      賦值與交換

      作用:給list容器賦值,以及交換list容器

      函數原型:

      • list& operator=( const list& lst ) ; // 重載方式進行賦值

      • assign( begin() , end() ) ; //將區間[ begin , end)之間的元素賦值給本身

      • assign( n , elem ) ; //將 n 個 elem賦值給本身

      • swap( lst ) ; // 將容器 與 本身的元素互換

      示例:

      void PrintList( const list<int>& L)
      {
          for( list<int>::const_iterator it = L.begin(); it!=L.end(); it++ )
          {
               cout << *it << " " ;
          }
          cout << endl;
      }
      int main()
      {
          list<int>  L1;                                 //創建方法一:默認構造函數L1
          for( int i = 0 ; i<10; i++ )
               L1.push_back( i );
          PrintList(L1);
      
          list<int> L2( L1.begin() , L1.end() );         //創建方法二:將L1區間[ begin , end )之間的數據拷貝給L2
          PrintList(L2);
      
          list<int> L3( 10 ,100 );                       //創建方法三:將 10 個 100 拷貝給L3
          PrintList(L3);
          
          List<int> L4(L1);                              //創建方法四:將L1整個容器本身拷貝給L4
          PrintList(L4);
      
          List<int> L5;
          L5 = L1;                                       //賦值方式一:重載方式賦值
          PrintList(L5); 
      
          List<int> L6;
          L6.assign( L1.begin() , L1.end() );            //賦值方式二:將L1[begin ,end)之間的元素賦值給L6
          PrintList(L6); 
      
          List<int> L7;
          L7.assign( 10 , 200 );                         //賦值方式三:將10 個 200 賦值給L7
          PrintList(L7); 
          
          L7.swap( L6 );                                 //將容器L6 與容器 L7 進行元素交換
          PrintList(L6); 
          PrintList(L7); 
          
      }

      大小操作

      作用:獲取容器list的長度

      函數原型:

      • size( ) ; //返回元素個數

      • empty( ) ; // 判斷是否為空

      • resize( num ) ; //重新指定容器長度,容器變長,以默認值0填充,容器變短,超出的元素被刪除

      • resize( num , elem ) ; //重新指定容器長度,容器變長,以數值elem填充,容器變短,超出的元素被刪除

      示例:

      void PrintList( const list<int>& L)
      {
          for( list<int>::const_iterator it = L.begin(); it!=L.end(); it++ )
          {
               cout << *it << " " ;
          }
          cout << endl;
      }
      int main()
      {
          list<int>  L1;                                 
          for( int i = 0 ; i<10; i++ )
               L1.push_back( i );
          PrintList(L1);
      
          if( L1.empty())                                             // 判斷容器是否為空
          {
               cout << "L1 為空:" << endl;
          }
          else
          {
               cout << "L1不為空:" << endl;
               cout << "L1的元素個數為:" << L1.size() << endl;       //判斷容器的長度
          }
          
          L1.resize( 5 );                                             //重新指定容器大小為5,超出長度5的元素被刪除
          PrintList(L1);
          
          L1.resize(10 , 10000);                                     //重新指定容器大小為10,超出原有長度的位置用10000填充
          PrintList(L1);
      }

      插入和刪除

      作用:對list容器進行元素插入和刪除

      函數原型:

      • push_back( elem ); //尾部插入數據

      • push_front( elem ); //頭部插入數據

      • pop_back(); //刪除最后一個元素

      • pop_front(); //刪除第一個元素

      • insert( pos, elem ); //在迭代器pos位置插入數值elem

      • insert( pos , n , elem ); //在迭代器pos位置插入n個elem

      • insert( pos , begin , end ); //在迭代器pos位置插入從begin到end之間的元素

      • erase( pos ); //刪除迭代器pos位置的元素

      • erase( begin , end ); //刪除迭代器[ begin , end ) 之間的元素

      • remove( elem ); //刪除容器中與elem相同的所有元素

      示例;

      void PrintList( const list<int>& L)
      {
          for( list<int>::const_iterator it = L.begin(); it!=L.end(); it++ )
          {
               cout << *it << " " ;
          }
          cout << endl;
      }
      int main()
      {
          list<int> L;
          
          for(int i = 0;i<10; i++)
          {
              L.push_back(i);                 //尾部插入元素
              L.push_front(i);                //頭部插入元素
          }
          PrintList(L);
         
           L.pop_front();                      //刪除第一個元素
           L.pop_back();                       //刪除最后一個元素
           PrintList(L);
      
           list<int>::iterator it = L.begin();
           L.insert( it , 1000);               //在迭代器it位置插入1000
           L.insert( it++ ,5, 1000);           //在迭代器it++位置插入5個1000
           PrintList(L);
           
           L.remove( 10000 );                  //移除容器中與1000相同的所有元素
           PrintList(L);
      
           list<int> L1;
           L1.insert( L1.begin() , L.begin() , L.end() );     //將L[begin,end)之間的元素賦值給L1容器
           PrintList( L1 );
      
           L1.erase(L1.begin);                                //擦除迭代器位置的元素
           L1.earse( L1.begin() , L1.end() );                 //擦除容器從begin到end之間的元素
           PrintList( L1 );
      
           system("pause");
           return 0;
      }

      數據存取

      • 存取方式不是[]獲取,也不是at()獲取

      • 因為list容器本質是鏈表,既不是連續的內存,迭代器也不支持隨機訪問

      函數原型:

      • front(); // 返回第一個元素

      • back(); // 返回最后一個元素

      示例:

      void PrintList( const list<int>& L)
      {
          for( list<int>::const_iterator it = L.begin(); it!=L.end(); it++ )
          {
               cout << *it << " " ;
          }
          cout << endl;
      }
      int main()
      {
          list<int> L;
          
          for(int i = 0;i<10; i++)
          {
              L.push_back(i);                 //尾部插入元素
          }
          PrintList(L);
      
          cout << "第一個元素是:" << L.front() << endl;
          cout << "最后一個元素是:" << L.end() << endl;
          
          list<int>::iterator it = L.begin();
          it++;                    //√,沒報錯,說明迭代器支持前移
          it--;                    //√,沒報錯,說明迭代器支持后移
          //it = it + 1 ;         //×,編譯器報錯,說明迭代器不支持地址隨機跳躍,it = it-1也一樣不行
          //it = it + 2 ;         //×,編譯器報錯,說明迭代器不支持地址隨機跳躍,it = it-2也一樣不行
          //it = it + x ;         //×,編譯器報錯,說明迭代器不支持地址隨機跳躍,it = it-x也一樣不行
        
         system("pause");
         return 0;
      }

      反轉和排序規則

      作用:將容器中的元素反轉,以及對元素進行排序

      函數原型:

      • reverse(); //容器元素進行反轉

      • sort(); //容器元素進行從小到大排序,沒有迭代器參數,所以這個是內部成員函數,不是標準算法

      • //對于定義數據類型,必須要指定排序規則(高級排序),否則編譯器是不知道怎么排的

      示例:

      void PrintList( const list<int>& L)
      {
          for( list<int>::const_iterator::it = L.begin(); it!= L.end(); it++ )
          {
               cout << *it << " " ;
          }
          cout << endl;
      }
      bool mycompare(int v1 , int v2)          //指定排序規則,提供降序方法
      {
          return v1 > v2 ;                     //指定規則:第一個數 > 第二個數,代表降序
      }
      
      int main()
      {
          list<int> L;
          L.push_back(10);
          L.push_back(30);
          L.push_back(50);
          L.push_back(80);
          L.push_back(60);
          PrintList(L);                    //反轉前
         
          L.reverse();
          PrintList(L);                    //反轉后
      
          //sotr( L.begin(), L.end() );    //×,因為list迭代器不支持隨機訪問,所以不能使用標準算法庫的函數
          L.sort();                        //√,list容器內部提供一個自己的排序算法,排序是從小到大
          L.sort(myCompare);               //√,提供一個降序排序,這是底層算法決定的,會用就行
           
          system("pause");
          return 0;
      }

      set/multiset容器

      • 在set/multiset容器中,所有的元素都會在插入時自動排序,默認從小到大

      • 兩者屬于關聯式容器,內部結構是用二叉樹實現的

      • 兩者的頭文件都是 #include<set>

      set和multiset的區別:

      • set容器不允許有重復的元素出現,即使強制插入重復元素,插入也會失敗

      • multiset容器可以有重復的元素出現

      set的構造函數

      作用:創建set容器

      函數原型:

      • set<T> st ; // 默認構造函數

      • set(const set& st) ; //拷貝構造函數

      set的賦值函數

      函數原型:

      • set& operator( const set& st); // 函數重載實現賦值操作

      set的插入和刪除

      函數原型:

      • insert( elem ) ; // 插入只有insert()方式,不能指定位置,因為會自動排序

      • erase(pos) ; // 刪除迭代器pos位置的元素

      • erase ( elem ); //刪除數值為elem的元素

      • erase( begin , end ); //刪除[ begin,end)之間的元素

      • clear(); //清除所有元素

      set的大小和交換

      • 作用:統計容器的大小以及交換set容器

      • 沒有重新指定容器大小的操作,因為會有默認值填充位置,而set容器中不能出現重復的元素

      函數原型:

      • size( ); //返回容器中元素個數

      • empty( ); //判斷容器是否為空

      • swap( ); // 交換兩個集合容器中的數據

      set的查找和統計

      作用:對set容器進行數據查找以及數據統計

      函數原型:

      • find( key ); //查找一個元素是否存在,存在則返回元素迭代器位置,不存在返回set.end()

      • cout( key ); //統計key的元素個數,對于set而言不是0就是1,因為不允許有重復元素

      示例:

      void PrintSet( const set<int>& s)
      {
          for(set<int>::const_iterator it = s.begin();it!= s.end();it++)
          {
               cout << *it << " " ;
          }
          cout << endl;
      }
      int main()
      {
         set<int> s1;                                      //默認構造函數創建set容器s1
         s1.insert(10);                                    //插入一些數據
         s1.insert(50);
         s1.insert(30);
         s1.insert(60);
         s1.insert(20);
         PrintSet(s1);
       
         set<int> s2(s1);                                  //拷貝構造函數,創建容器s2
         PrintSet(s2);
         
         set<int> s3;              
         s3 = s1;                                          //重載方式進行賦值
         PrintSet(s3);
      
         if( s1.empty())
         {
              cout << "容器s1為空" << endl;
         }
         else
         {
              cout << "容器s1不為空" << endl;
              cout << "容器s1的個數:" << s1.size() << endl;
         }
      
         set<int> s4;
         for(int i = 0; i<10;i++)
        {
           s4.insert(i);                                      //插入一些元素
        } 
         PrintSet(s4);             
        
         s4.swap(s1);                                         //s4與s1容器進行交換  
         PrintfSet(s4);
        
         s4.erase( s4.begin() );                              //刪除迭代器位置begin的元素
         PrintSet(s4); 
         s4.erase( 5 );                                       // 刪除數值為 5 的元素
         PrintSet(s4); 
         erase(s4.begin() , s4.end());                        // 刪除在[begin,end)區間之間的元素
         PrintSet(s4);
         s4.clear();                                          //清除所有元素
         PrintSet(s4);
      
         set<int>::iterator pos = s1.find(30);               //查找元素是否存在,存在則返回元素的迭代器位置
         if( pos != s1.end() )                                
         {
             cout << "找到元素:" << *pos << endl;
         }
         else
         {
            cout << "沒有找到元素" << endl;
         }
        
         cout << "統計元素個數" << s1.count(30) << endl;      //統計元素30的個數
                                                              //對于set容器而言,不是0就是1,因為其不會出現重復的元素
      }

      set和multiset的區別

      • set不可以插入重復數據,而multiset可以

      • set插入數據會返回插入結果,同時也是這樣檢測是不是重復元素

      • multiset插入數據不會檢測,因此可以插入重復數據

      set.insert()的函數原型:

      • _Pairib insert( value_type&& _Val) ;

      • using _Pairib = pair<inerator , bool>; //set.insert()的返回值類型是對組,返回迭代器位置和插入結果

      multiset.insert()的函數原型:

      • iterator insert(value_type&& _Val); //multiset.insert()返回值類型只有迭代器位置,沒有檢測結果

      示例:

      void PrintfSet( set<int>& s)
      {
          for( set<int>::iterator it = s.begin(); it != s.end(); it++)
          {
             cout << *it << " " ;
          }
          cout << endl;
      }
      int main()
      {
          set<int> s;
          pair<set<int>::iterator, bool> ret = s.insert(10);      //獲取第一次插入數據的迭代器位置和插入結果
          if(ret.second)                                          //ret.second存放的就是插入結果
               cout << "第一次插入成功" << endl;
          else
               cout << "第一次插入失敗" << endl;
      
          ret = s.insert(10);                                    //獲取第二次插入的迭代器位置和插入結果
          if(ret.second)                  
               cout << "第二次插入成功" << endl;
          else
               cout << "第二次插入失敗" << endl;                 //因為是插入了相同的元素,所以這一次的插入失敗
           
          multiset<int> ms;                                      //multiset容器是可以插入相同元素的
          ms.insert(30);
          ms.insert(30);
          PrintSet(ms);                        
      }

      pair對組創建

      作用:成對出現的數據,可以返回兩個數據

      創建方法的函數原型:

      • pair<type , type> p (value1, value2 );

      • pair<type , type> p = make_pair( value1, value2 );

      示例:

      int main()
      {
         pair<string , int> p1("Tom" , 20);                       // 第一種創建方式
         cout << "姓名:" << p1.first << "年齡:" << p1.second << endl;
      
         pair<string , int> p2 = make_pair("jerry" , 30);         // 第二種創建方式
         cout << "姓名:" << p2.first << "年齡:" << p2.second << endl;
      
        system("pause");
        return 0;
      }

      set容器排序

      • 作用:set容器排序是默從小到大,但是可以可以通過仿函數來改變排序規則

      • 要在插入數據之前就指定排序規則

      • 如果是自定義數據類型,一定要指定排序規則

      示例1:指定排序規則——內置數據類型

      class Mycompare                   
      {
      public:
             bool operator()( int val1,int val2)
             {
                 return val1 > val2 ;
             }
      };
      int main()
      {
          //set<int> s1;               //這么寫,那插入的數據肯定就是默認從下到大了
          set<int , MyCompare> s1;     // 既然要指定排序規則,就要在插入之前做好指定,由MyCompare類型來指定
                                       //而set<>中的參數只能是數據類型,所以MyCompare得用數據類型來表示,不能用函數名
          s1.insert(30);               //現在插入的數據,就會根據Mycompare來降序排或者升序排
          s1.insert(10); 
          s1.insert(50);
          s1.insert(40);
          s1.insert(20);
          
          for( set<int,MyCompare>::iterator it = s1.begin(); it!=s1.end(); it++ )
          {
               cout << *it << " ";
          }
          cout << endl;
      }

      示例2:指定排序規則——自定義數據類型

      class Person
      {
      public:
             Person(string name , int age)
             {
                this->m_name = name;
                this->m_age = age;
             }
             string  m_name;
             int  m_age;
      }
      class ComparePerson
      {
      public:
             bool operator()(set<Person>& p1 , set<Person>& p2)
             {
                 return p1.m_age > p1.m_age ;                  //指定規則為按照年齡進行降序排序
             }
      };
      int main()
      {
           set<person , ComparePerson> s;
          
           Person p1("劉備" , 40);           //如果沒有指定排序規則的話,set容器都不知道按照什么進行排序,容器自己都蒙了
           Person p2("關羽" , 30); 
           Person p3("張飛" , 28);
           Person p4("趙云" , 20);
        
           s.insert(p1);                     //此時插入數據,容器就會按照年齡來進行排序
           s.insert(p2);
           s.insert(p3);
           s.insert(p4);
      
           for(set<Person , ComparePerson>::iterator it = s.begin(); it != s.s.end(); it++)
           {
                //cout << "姓名:" << *it.m_name << "年齡:" << *it.m_age << endl;
                  cout << "姓名:" << it->m_name << "年齡:" << it->m_age << endl;
           }
      
           system("pause");
           return 0;
      }

      map/multimap容器

      • map/multimap都是關聯式容器,內部結構是二叉樹

      • map容器中的元素全是pair對組

      • pair中第一個元素為key(鍵值,起到索引作用),第二個元素為value(實值)

      • 所有的元素都會根據元素的key鍵值自動排序,默認從小到大

      • 可以根據鍵值快速找到value值,高效率高性能

      • map/multimap兩者的頭文件都是#include<map>

      map和multimap的區別:

      • map容器中不允許有重復的key值元素

      • multimap容器中允許有重復的key值元素

      map的構造函數

      函數原型;

      • map<T1 , T2> mp ; // 默認構造函數

      • map<const map& mp> ; // 拷貝構造函數

      map的賦值函數

      函數原型:

      • map& operator=( const map& mp) ; // 重載等號操作符進行賦值操作

      map的大小和交換

      函數原型:

      • size(); // 返回元素個數

      • empty(); // 判斷容器是否為空

      • swap(); // 交換兩個map容器

      map的插入和刪除

      函數原型:

      • insert(elem); // 插入元素,地址沒法自定義,因為會自動排序

      • erase(key); // 刪除key值的元素

      • erase(pos); // 刪除迭代器pos位置的元素

      • erase(begin , end); // 刪除區間為[begin,end)之間的元素

      • clear(); // 清除容器中所有元素

      map的查找和統計

      函數原型:

      • find( key ); //查找元素是否存在,存在則返回元素迭代器,不存在則返回map.end() ;

      • count( key ); //返回鍵值為key的元素的個數,對于map,不是0就是1,因為不允許出現重復元素

      示例:

      void PrintMap( map<int , int>& m )
      {
          for( map<int,int>::iterator::it = m.begin(); it != m.end(); it++)
          {
              cout << "key = " << *it.first << "value = " << it->second << endl;
          }
          cout << endl;
      }
      int main()
      {
           map<int,int> m1;                                      // 創建方式一:默認構造函數
           
           m1.insert( pair<int,int>(1,10) );                      //插入方式一
           m1.insert( pair<int,int>(3,30) );
           m1.insert( make_pair(2,20) );                          //插入方式二
           m1.insert( make_pair(4,40) );
           m1.insert( map<int,int>::value_type(6,60))             //插入方式三
           m1.insert( map<int,int>::value_type(7,70))
           m1[6] = 90;                                            //插入方式四,不建議用,如果插錯了,value會被賦成0
           m1[7] = 80;                                            //不建議用這方式賦值,只適合用來訪問
           PrintMap(m1);
          
           map<int , int> m2(m1);                                //創建方式二:拷貝構造函數
           PrintMap(m2);
      
           map<int,int> m3;                                      //重載運算符進行賦值操作
           m3 = m1;
      
           if( m3.empty())                                       // 判斷容器是否為空
                cout << "map容器為空" << endl;
           else
           {
                cout << "map容器不為空"  << endl;
                cout << "容器元素個數:" << m3.size() << endl;    // 獲取容器元素個數
           }
      
            map<int , int> m4;
            for(int i = 0;i<10 ;i++)
            {
                 m4.insert( pair<int,int>(i,i*10) );
            }
            PrintMap(m4);                 // 容器交換前
            
            m4.swap(m1);                  //容器m4與m1進行交換
            PrintMap(m4);                 //跟容器m1交換后
      
            m4.erase(m4.begin());          //刪除迭代器begin位置的元素
            PrintMap(m4);
            m4.erase(20);                  //刪除key值為20的元素
            PrintMap(m4);
            m4.erase(m4.begin , m4.end);   //刪除區間為 [m4.begin , m4.end())之間的元素
            PrintMap(m4);
            
            m4.clear();                     //清除容器m4中的所有元素
            PrintMap(m4);
      
            map<int,int>::iterator pos = m1.find(3);       //找到元素3,如果存在,則返回元素迭代器元素
            if( pos != m1.end())                           //如果不存在,則返回m1.end()
            {
                cout << "找到了元素" << endl;
                cout << "key = " << *pos.first << "value = " << "*pos.second" << endl; 
            }
            else
            {
                cout << "未找到元素" << endl;
            }
            
            int num = m1.count(3);                           //獲取key = 3 的元素個數
            cout << "num = " << num << endl;                 //對于map容器,不是1就是0
       
            system("pause");
            return 0;
      }

      map容器排序

      • 作用:利用仿函數,改變排序規則

      • 排序規則一定要在插入數據前指定

      示例:

      class MyCompare
      {
      public:
             bool operator()(int v1,int v2)
             {
                  return v1 > v2 ;             //指定降序的排序規則
             }
      };
      int main()
      {
           map<int,int,MyCompare> m;                                     
           
           m.insert( pair<int,int,MyCompare>(1,10) );                      
           m.insert( pair<int,int,MyCompare>(3,30) );
           m.insert( make_pair(2,20) );                         
           m.insert( make_pair(4,40) );
           m.insert( make_pair(6,60) );
           m.insert( make_pair(5,50) );
           
          for( map<int,int,MyCompare>::iterator::it = m.begin(); it != m.end(); it++)
          {
              cout << "key = " << *it.first << "value = " << it->second << endl;
          }
         
          system("pause");
          return 0;
      }

      函數對象/仿函數

      • 本質上是一個類,重載函數調用運算符的類,其創建的對象也就被稱為函數對象

      • 因為函數對象在發生重載時,就像函數調用一樣,所以也叫做仿函數

      • 說白了就是一個對象,一個可以當函數用的對象

      特點:

      • 函數對象在使用時跟函數差不多,可以有參數,也可以有返回值

      • 函數對象可以有自己的狀態,函數沒有

      • 函數對象可以作為參數傳遞

      示例:

      calss MyAdd
      {
      public:
            int oprator()(int v1, int v2)                  //特點1:本質是一個類,函數對象既可以有參數,也可以有返回值
            {
                return v1+v2;
            }
      };
      clss MyPrint
      {
      public:
            MyPrint()
            {
                 this->count++;                             //特點2:函數對象可以擁有自己的狀態
            }
            void operator()(string str)
            {
                 cout << str << endl;
            }
            int count;
      };
      void test(MyPrint& mp , string str)                   //特點3:可以作為函數參數傳遞
      {
           mp(str);
      }
      int main()
      {
           MyAdd add;
           cout << "add = " << add(10 , 30) << endl;       //特點1:像普通函數一樣調用
      
      
          MyPrint print;
          print("Hello C++");                             //特點2:可以有自己的狀態,比如獲取自己被調用了幾次
          print("Hello C++");
          print("Hello C++");
          print("Hello C++");
          cout << "print被調用的次數為:" << print.count << endl;      
      
          test(print , "Hello C++");                      //特點3:函數對象作為參數進行傳遞
      }

      謂詞

      • 返回bool類型的仿函數,就稱為謂詞

      • 如果operator()接受一個參數,就是一元謂詞

      • 如果operator()接受兩個參數,就是二元謂詞

      一元謂詞

      • 如果operator()接受一個參數,就是一元謂詞

      示例:

      class GreatFive
      {
      public:
          bool operator()(int val)         // 返回值是bool類型的仿函數,并且只有一個參數,就稱為一元謂詞
          {
                return val > 5;            
          }
      };
      int main()
      {
          vector<int> v;
          for(int i=0;i<10;i++)
          {
              v,push_back(i);
          }
          //功能,找到容器中,元素大于5的元素
          // GreatFive()是一元謂詞,是一個匿名的函數對象,功能是說明要找到大于5的元素
          vectot<int>::iterator it = find_if( v.begin(), v.end().Greatfive() );
          if( it == v.end() )
          {
               cout << "沒找到" << endl;
          }
          else
          {
               cout << "找到了" << *it << endl;
          }
      
          return 0;
      }

      二元謂詞

      • 如果operator()接受兩個參數,就是二元謂詞

      示例:

      class MyCompare
      {
      public:
            bool operator()(int val1,int val2)     // 返回類型為bool類型,并且有兩個參數,所以是二元謂詞
            {
                  return val1 > val2 ;            // 功能是從大到小
            }
      };
      int main()
      {
          vector<int> v;
          v.push_back(40);
          v.push_back(30);
          v.push_back(50);
          v.push_back(20);
          v.push_back(70);
          v.push_back(10);
         
          sort( v.begin() , v.end() );      // 默認是從小到大
      
          //利用仿函數改變排序規則,從大到小
          sort( v.begin() , v.end(), MyCompare() );     
      
          return 0;
      }

      內建函數對象

      • STL內建了一些已經封裝好了的函數對象

      • 這些對象是由仿函數所產生的,用法和一般對象一樣

      • 需要加入頭文件#include<functional>

      • 內建函數對象是已經寫好的標準算法入口,愿意你就用,不愿意就自己寫一個

      分類:

      • 算術仿函數

      • 關系仿函數

      • 邏輯仿函數

      算術仿函數

      作用:實現四則運算

      函數原型:

      • template<class T> T plus<T> // 加法仿函數,二元運算

      • template<class T> T minus<T> //減法仿函數,二元運算

      • template<class T> T multiplies<T> //乘法仿函數,二元運算

      • template<class T> T divides<T> //除法仿函數,二元運算

      • template<class T> T modulus<T> //取模仿函數,二元運算

      • template<class T> T negate<T> //取反仿函數 ,一元運算

      示例:

      #include<functional>
      int main()
      {
          negate<int> n;            //創建一個內建的取反對象
          cout << n(57) << endl;    //這就完成取反操作了
      
         plus<int> p;              //創建一個內建的加法對象,這里只需要聲明一個int的數據類型就好了,因為只有同一類型的才能算術運算
         cout << p(10,20) << endl; //這樣就完成加法操作了
      
         system("pause");
         return 0;
      }

      關系仿函數

      作用:實現關系對比

      函數原型:

      • template<class T> bool equal_to<T> // 等于

      • template<class T> bool not_equal_to<T> //不等于

      • template<class T> bool greater<T> //大于

      • template<class T> bool greater_equal<T> //大于等于

      • template<calss T> bool less<T> //小于

      • template<class T> bool less_equal<T> //小于等于

      示例:不用自己寫的仿函數,用內建函數對象來改變排序規則

      #include<vector>
      #include<algorithm>
      #include<functional>
      class MyCompare          
      {
      public:
            bool operator()(int val1, int val2)
            {
                return val1 > val2;
            }
      };
      
      int main()
      {
          vector<int> v;
          v.push_back(50);
          v.push_back(30);
          v.push_back(70);
          v.push_back(40);
          v.push_back(20);
          v.push_back(10);
          
          // sort(v.begin() , v.end(), MyCompare());     // 自己寫的反函數開改變排序規則,實現大于等于的降序
          sort(v.begin(), v.end(), greater<int>());      // 用內建函數對象來改變排序規則,實現大于等于的降序
         
          system("pause");
          return 0;
      }

      邏輯仿函數

      作用:實現邏輯運算

      函數原型:

      • template<class T> bool logical_and<T> // 邏輯與

      • template<class T> bool logical_or<T> //邏輯或

      • template<class T> bool logical_not<T> //邏輯非

      示例:用邏輯非操作將容器v1的元素取反并搬運到容器v2中

      #include<vector>
      #include<algorithm>
      #include<functional>
      int main()
      {
          vector<bool> v1;
          v1.push_back(true);
          v1.push_back(flase);
          v1.push_back(true);
          v1.push_back(flase);
      
          vector<bool> v2;
          v2.resize( v1.size() );         //重新指定容器v2的大小
          //transform這是標準算法,用于搬運元素
          //用邏輯非的規則將容器v1搬運到容器v2中
          transform(v1.begin(), v1.end(), v2.begin(), logical_not<bool>());     
        
          system("pause");
          return 0;
      }

      學習C++這一篇就夠了(基礎篇) https://mp.csdn.net/mp_blog/creation/editor/131559599

      學習C++這一篇就夠了(進階篇) https://mp.csdn.net/mp_blog/creation/editor/131565205

      先更新到這兒吧,需要后面在補充。

      希望以上內容可以幫助到大家。

      祝各位生活愉快。

      ?
      posted on 2023-07-09 19:52  五月525  閱讀(170)  評論(0)    收藏  舉報



      主站蜘蛛池模板: 屁屁影院ccyy备用地址| 国产三级精品福利久久| 成人福利一区二区视频在线| 日本一区二区精品色超碰| 久久99九九精品久久久久蜜桃| 成人午夜看黄在线尤物成人| 云林县| 成A人片亚洲日本久久| 久久国产精品乱子乱精品| 加勒比在线中文字幕一区二区| 柘荣县| 欧产日产国产精品精品| 国产啪视频免费观看视频 | 国产精品嫩草99av在线| 国日韩精品一区二区三区| 毛片内射久久久一区| 亚洲天堂精品一区二区| 精品久久综合日本久久网| 四虎成人精品无码| 白嫩少妇无套内谢视频| 国产日本一区二区三区久久| 久久夜色精品国产噜噜亚洲sv | 大地资源免费视频观看| 亚洲性av网站| jizz国产免费观看| 精品自拍偷拍一区二区三区| 1769国内精品视频在线播放 | 东京热大乱系列无码| 亚洲中文字幕久久精品品| 欧美成人h精品网站| 日本中文字幕不卡在线一区二区| 国产乱码精品一区二三区| 一区二区视频| 国产中文三级全黄| 视频一区二区不中文字幕| 免费观看全黄做爰大片| 中文字幕国产日韩精品| 国产第一页浮力影院入口| 波多野结衣美乳人妻hd电影欧美| av无码精品一区二区三区| 少妇高潮喷水正在播放|