C++知識點總結匯總

這幾天簡略的把《C++ primer plus》過一遍(不多,總共才936頁( =•ω•= )),挑點書上有用的輔以網上查到的blog資料簡單總結一下,以後再細學C++

———————————————————————————————————
一套很好的C++教程

一.C++雜項總結

(1)C++支持連續賦值,從右往左int n=x=b=c=10;合法

(2)新的賦值方式:int n(32);std::cout<<n;

(3)用cout輸出十進制、十六進制和八進制顯示整數

C++ cout利用控制符dechexoct,分別輸出十進制、十六進制和八進制顯示整數.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
	int chest=42;
	int waist=42;
	int inseam=42;
	cout<<hex<<"waist="<<waist<<" (16/hexadecimal for 42)"<<endl;//十六進制
	cout<<oct<<"inseam="<<inseam<<" (8/octal for 42)"<<endl;//八進制
	cout<<dec<<"chest="<<chest<<" (10/decimal for 42)"<<endl;//十進制
}

輸出:

waist=2a (16/hexadecimal for 42)
inseam=52 (8/octal for 42)
hest=42 (10/decimal for 42)

(4)puts("'");cout<<'\'';//(^_^)

(5)變量auto

如果使用關鍵字auto,而不指定變量的類型,編譯器將把變量的類型設置成與初始值相同;

auto n=100;//n is int ;
auto x=1.5;//x is double;
auto y=1.3e12L;//y is long double;
std::vector<double>v;
auto it=v.begin();//等同於 {std::vector<double>::iterator it=v.begin();}

(6) 偷個懶讓編譯器幫忙算

short things[]={1,5,8};
int num_elements=sizeof things/sizeof(short);

(7)

char s[4] {'h','i',112,'\0'};//allowed;112會轉換成ASCII碼所對應的字符

(8)C++11中新增的基於範圍的for循環

#include <iostream>
#include <string>
using namespace std;
int main ()
{
    string planets []= { "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto(a dwarf planet)" };
    cout << "Here are the planets: \n ";
    for (auto val : planets)//C++11才能用(沒什麼用)
        cout << val << endl;
    return 0;
}

(9)頭文件cctype中的字符函數

函數名稱 返回值
isalnum() 如果參數是字母或數字,該函數返回true
isalpha() 如果參數是字母,該函數返回true
iscntrl() 如果參數是控制字符,該函數返回true
isdigit() 如果參數是數字(0~9),該函數返回true
isgraph() 如果參數是除空格之外的打印字符,該函數返回true
islower() 如果參數是小寫字母,該函數返回true
isprint() 如果參數是打印字符(包括空格),該函數返回true
ispunct() 如果參數是標點符號,該函數返回true
isspace() 如果參數是標準空白字符,如空格、進紙、換行符、回車、水平製表符或者垂直製表符,該函數返回true
isupper() 如果參數是大寫字母,該函數返回true
isxdigit() 如果參數是十六進制數字,即09、af或A~F,該函數返回true
tolower() 如果參數是大寫字符,則返回其小寫,否則返回該參數
toupper() 如果參數是小寫字符,則返回其大寫,否則返回該參數

(10)位運算詳解+競賽常見用法總結

二.內聯函數

調用內聯函數比調用普通函數更快但更消耗內存

inline int x()
{
   .......
}

三. 引用變量

將temp作爲rate變量的別名

int rate;
int & temp=rate;

temp與rate的地址會相同,值相同,操作後一塊改變

#include <iostream>
#include <string>
using namespace std;
void add(int &x)//x和temp均爲rate的引用變量,改變其中任意一個剩餘的都會受其影響
{
    x++;
    cout<<x<<" "<<endl;
    cout<<&x<<" "<<endl;
}
int main ()
{
    int rate=100;
    int & temp=rate;
    rate++;
    cout<<rate<<" "<<temp<<endl;
    add(rate);
    cout<<rate<<" "<<temp<<endl;
    cout<<&rate<<" "<<&temp<<endl;
    return 0;
}

輸出:

101 101
102
0x6dfee8
102 102
0x6dfee8 0x6dfee8

引用變量適合用於結構體中
如果不希望函數修改傳入的值,可以使用const避免失誤void add(const int &x)

四.函數重載

函數重載是一種特殊情況,C++允許在同一作用域中聲明幾個類似的同名函數,這些同名函數的形參列表(參數個數,類型,順序)必須不同,常用來處理實現功能類似數據類型不同的問題。
會自動選擇,所以很🐂🍺
函數重載的詳解

五.函數模板

template <typename AnyType>

二者完全相同,這裏推薦使用前者,因爲class作用很多容易弄混

template <class AnyType>

使用函數模板就再不用重新寫一個函數了,省時省力

#include <iostream>
using namespace std;
template<typename T>
void Swap(T & x, T & y)
{
    T tmp = x;
    x = y;
    y = tmp;
}
int main()
{
    int n = 1, m = 2;
    Swap(n, m);  //編譯器自動生成 void Swap (int &, int &)函數
    double f = 1.2, g = 2.3;
    Swap(f, g);  //編譯器自動生成 void Swap (double &, double &)函數
    return 0;
}

(1)類模板

類模板詳解
模板函數詳解

六.class類

類是創建對象的模板,一個類可以創建多個對象,每個對象都是類類型的一個變量;創建對象的過程也叫類的實例化。每個對象都是類的一個具體實例(Instance),擁有類的成員變量成員函數
有些教程將類的成員變量稱爲類的屬性(Property),將類的成員函數稱爲類的方法(Method)。在面向對象的編程語言中,經常把函數(Function)稱爲方法(Method)。
與結構體一樣,類只是一種複雜數據類型的聲明,不佔用內存空間。而對象是類這種數據類型的一個變量,或者說是通過類這種數據類型創建出來的一份實實在在的數據,所以佔用內存空間。

(1)類的定義

類是用戶自定義的類型,如果程序中要用到類,必須提前說明,或者使用已存在的類(別人寫好的類、標準庫中的類等),C++語法本身並不提供現成的類的名稱、結構和內容。
類與結構體很類似!!

注意在類定義的最後有一個分號:;

(2)完整示例

#include<iostream>
using namespace std;
typedef long long ll;
const ll N=1e5+7;
class Student
{
public :
    //類所包含的成員變量
    string name;//char *name;
    ll age;
    double score;
    //類所包含的成員函數
    void say()
    {
        cout<<name<<"'s age is "<<age<<" ,and his total score is "<<score<<"."<<endl;
    }
};
int main()
{
    Student *p = new Student;//用new來分配內存
    Student stu;//創建對象
    p->name = "Meng";
    p->age = 19;
    p->score = 97.5d;
    p->say();
    delete p;//釋放內存
    return 0;
}

(3)成員函數與成員變量

類的成員變量和普通變量一樣,也有數據類型和名稱,佔用固定長度的內存。但是,在定義類的時候不能對成員變量賦值,因爲類只是一種數據類型或者說是一種模板,本身不佔用內存空間,而變量的值則需要內存來存儲。

類的成員函數也和普通函數一樣,都有返回值和參數列表,它與一般函數的區別是:成員函數是一個類的成員,出現在類體中,它的作用範圍由類來決定;而普通函數是獨立的,作用範圍是全局的,或位於某個命名空間內。
成員函數最好放在類體裏,如果放到外面必須要在函數名前面加上類名予以限定。
示例:

#include<iostream>
using namespace std;
typedef long long ll;
const ll N=1e5+7;
class Student{
public:
    char *name;
    int age;
    float score;

    void say();  //內聯函數聲明,可以增加 inline 關鍵字,但編譯器會忽略
};

//函數定義
inline void Student::say()
{
    cout<<name<<"的年齡是"<<age<<",成績是"<<score<<endl;
}
int main()
{

}

可以有這樣的操作 但是不推薦

(4)public private

C++通過 public、protected、private 三個關鍵字來控制成員變量和成員函數的訪問權限,它們分別表示公有的、受保護的、私有的,被稱爲成員訪問限定符。所謂訪問權限,就是你能不能使用該類中的成員。

C++ 中的 public、private、protected 只能修飾類的成員,不能修飾類,C++中的類沒有共有私有之分。

在類的內部(定義類的代碼內部),無論成員被聲明爲 public、protected 還是 private,都是可以互相訪問的,沒有訪問權限的限制。

在類的外部(定義類的代碼之外),只能通過對象訪問成員,並且通過對象只能訪問 public 屬性的成員,不能訪問 private、protected 屬性的成員。

#include <iostream>
using namespace std;

//類的聲明
class Student{
private:  //私有的
    string m_name;
    int m_age;
    double m_score;

public:  //共有的
    void setname(string name);
    void setage(int age);
    void setscore(double score);
    void show();
};

//成員函數的定義
void Student::setname(string name){
    m_name = name;
}
void Student::setage(int age){
    m_age = age;
}
void Student::setscore(double score){
    m_score = score;
}
void Student::show(){
    cout<<m_name<<"'s age is "<<m_age<<" ,and his total score is "<<m_score<<"."<<endl;
}

int main()
{
    Student stu;
    stu.setname("Meng");
    stu.setage(19);
    stu.setscore(97.5d);
    stu.show();
    return 0;
}

根據C++軟件設計規範,實際項目開發中的成員變量以及只在類內部使用的成員函數(只被成員函數調用的成員函數)都建議聲明爲
private,而只將允許通過對象調用的成員函數聲明爲 public。

成員變量大都以m_開頭,這是約定成俗的寫法,不是語法規定的內容。以m_開頭既可以一眼看出這是成員變量,又可以和成員函數中的形參名字區分開。

給成員變量賦值的函數通常稱爲 set 函數,它們的名字通常以set開頭,後跟成員變量的名字;讀取成員變量的值的函數通常稱爲 get 函數,它們的名字通常以get開頭,後跟成員變量的名字。
所謂封裝,是指儘量隱藏類的內部實現,只向用戶提供有用的成員函數。

(5)構造函數

方便class的賦值
大致由三個部分組成

public:
    //聲明構造函數
    Student(string name, int age, float score);
    //聲明普通成員函數
    void show();
Student::Student(string name, int age, float score){
    m_name = name;
    m_age = age;
    m_score = score;
}
Student stu("Meng", 19, 97.5f);

構造函數的重載
構造函數詳解

(6)this指針

this 只能用在類的內部,通過 this 可以訪問類的所有成員,包括 private、protected、public 屬性的。

本例中成員函數的參數和成員變量重名,只能通過 this 區分。如:this -> name = name;
注意this是一個const指針

void Student::printThis(){
    cout<<this<<endl;
}
Student *pstu1 = new Student;
pstu1 -> printThis();
cout<<pstu1<<endl;

輸出的是地址
詳解

(7)友元函數

藉助友元(friend),可以使得其他類中的成員函數以及全局範圍內的函數訪問當前類的 private 成員。友元函數可以訪問當前類中的所有成員,包括 public、protected、private 屬性的。

注意,友元函數不同於類的成員函數,在友元函數中不能直接訪問類的成員,必須要藉助對象。
詳解

七.重載運算符

運算符重載是通過函數實現的,它本質上是函數重載。

(1)類的重載運算符

類的重載+運算符,要在類裏聲明

........
public:
    void display() const;
    //聲明爲友元函數
    friend complex operator+(const complex &A, const complex &B);
........
//在全局範圍內重載+
complex operator+(const complex &A, const complex &B){
    complex C;
    C.m_real = A.m_real + B.m_real;
    C.m_imag = A.m_imag + B.m_imag;
    return C;
}

當執行c3 = c1 + c2;語句時,編譯器檢測到+號兩邊都是 complex 對象,就會轉換爲類似下面的函數調用: c3 = operator+(c1, c2);

(2)結構體的重載運算符

本題要求總分相同的,約定編號較小的選手排名靠前。可以在結構體內直接重載運算符<。

struct person
{
    ll s,idx,w;
    bool operator<(const person &t)const
    {
        if(t.s!=s)return s>t.s;
        return idx<t.idx;
    }
}p[N],loser[N],winer[N];

重載運算符<以後直接sort即可實現

sort(p+1,p+1+2*n);

詳解

(3)重載限制

多數C++運算符都可以重載。但是還存在着一些限制。

  1. 重載後的運算符必須至少有一個操作數是用戶自定義的類型,這將防止用戶爲標準類型重載運算符。
  2. 使用運算符時不能違反運算原來的句法規則。
  3. 不能創造新的運算符。
  4. 不能重載下面的這些運算符。
sizeof	sizeof運算符
.:	成員運算符
.*	成員指針運算符
::	作用域解析運算符
?:	條件運算符
typeid	一個RTTI運算符
const_cast	強制類型轉換運算符
dynamic_cast	強制類型轉換運算符
reinterpret_cast	強制類型轉換運算符
static_cast	強制類型轉換運算符

大多數運算符都可以通過成員或非成員函數進行重載,但這些運算符只能通過成員函數進行重載:

=	賦值運算符
()	函數調用運算符
[]	下標運算符
->	通過指針訪問類成員的運算符

八.string常用函數總結

(1)字符串的比較

1. C ++字符串支持常見的比較操作符>,>=,<,<=,==,!=,甚至支持string與C-string的比較如 str<”hello”
在使用>,>=,<,<=這些操作符的時候是根據“當前字符特性”將字符按字典順序進行逐一得 比較。字典排序靠前的字符小,
比較的順序是從前向後比較,遇到不相等的字符就按這個位置上的兩個字符的比較結果確定兩個字符串的大小(前面減後面)
同時,string (“aaaa”) <string(aaaaa)

2. 另一個功能強大的比較函數是成員函數compare()。他支持多參數處理,支持用索引值和長度定位子串來進行比較。
他返回一個整數來表示比較結果,返回值意義如下:0:相等 1:大於 -1:小於 (A的ASCII碼是65,a的ASCII碼是97,0的ASCII碼是48)

(2). string的插入:push_back() 和 insert()

void  test4()
{
    string s1;

    // 尾插一個字符
    s1.push_back('a');
    s1.push_back('b');
    s1.push_back('c');
    cout<<"s1:"<<s1<<endl; // s1:abc

    // insert(pos,char):在制定的位置pos前插入字符char
    s1.insert(s1.begin(),'1');
    cout<<"s1:"<<s1<<endl; // s1:1abc
}

輸出:

s1:abc
s1:1abc

(3)字符串的拼接append()/直接+

append函數是向string的後面追加字符或字符串。
string支持直接s1+=s2;

1.向string的後面加string的一部分

string s1 = “hello “, s2 = “wide world “;
s1.append(s2, 5, 5); ////把字符串s2中從5開始的5個字符連接到當前字符串的結尾
s1 = “hello world”;
string str1 = “hello “, str2 = “wide world “;
str1.append(str2.begin()+5, str2.end()); //把s2的迭代器begin()+5和end()之間的部分連接到當前字符串的結尾
str1 = “hello world”;

2.向string後面加多個字符

string s1 = “hello “;
s1.append(4,!); //在當前字符串結尾添加4個字符!
s1 = “hello !!!!;

3.用append()和"+"

string s1 = “hello “; string s2 = “wide “; string s3 = “world “;
s1.append(s2); s1 += s3; //把字符串s連接到當前字符串的結尾
s1 = “hello wide “; s1 = “hello wide world “;

(4) string的刪除:erase()

1. iterator erase(iterator p);//刪除字符串中p所指的字符

2. iterator erase(iterator first, iterator last);//刪除字符串中迭代器

區間[first,last)上所有字符

3. string& erase(size_t pos = 0, size_t len = npos);//刪除字符串中從索引

位置pos開始的len個字符

4. void clear();//刪除字符串中所有字符
void test6()
{
    string s1 = "123456789";


    // s1.erase(s1.begin()+1);              // 結果:13456789
    // s1.erase(s1.begin()+1,s1.end()-2);   // 結果:189
    s1.erase(1,6);                       // 結果:189
    string::iterator iter = s1.begin();
    while( iter != s1.end() )
    {
        cout<<*iter;
        *iter++;
    }
    cout<<endl;

}

(5)string的查找:find

1. size_t find (constchar* s, size_t pos = 0) const;

  //在當前字符串的pos索引位置開始,查找子串s,返回找到的位置索引,

    -1表示查找不到子串

2. size_t find (charc, size_t pos = 0) const;

  //在當前字符串的pos索引位置開始,查找字符c,返回找到的位置索引,

    -1表示查找不到字符

3. size_t rfind (constchar* s, size_t pos = npos) const;

  //在當前字符串的pos索引位置開始,反向查找子串s,返回找到的位置索引,

    -1表示查找不到子串

4. size_t rfind (charc, size_t pos = npos) const;

  //在當前字符串的pos索引位置開始,反向查找字符c,返回找到的位置索引,-1表示查找不到字符

5. size_tfind_first_of (const char* s, size_t pos = 0) const;

  //在當前字符串的pos索引位置開始,查找子串s的字符,返回找到的位置索引,-1表示查找不到字符

6. size_tfind_first_not_of (const char* s, size_t pos = 0) const;

  //在當前字符串的pos索引位置開始,查找第一個不位於子串s的字符,返回找到的位置索引,-1表示查找不到字符

7. size_t find_last_of(const char* s, size_t pos = npos) const;

  //在當前字符串的pos索引位置開始,查找最後一個位於子串s的字符,返回找到的位置索引,-1表示查找不到字符

8. size_tfind_last_not_of (const char* s, size_t pos = npos) const;

 //在當前字符串的pos索引位置開始,查找最後一個不位於子串s的字符,返回找到的位置索引,-1表示查找不到子串
void test8()
{
    string s("dog bird chicken bird cat");

    //字符串查找-----找到後返回首字母在字符串中的下標

    // 1. 查找一個字符串
    cout << s.find("chicken") << endl;        // 結果是:9

    // 2. 從下標爲6開始找字符'i',返回找到的第一個i的下標
    cout << s.find('i',6) << endl;            // 結果是:11

    // 3. 從字符串的末尾開始查找字符串,返回的還是首字母在字符串中的下標
    cout << s.rfind("chicken") << endl;       // 結果是:9

    // 4. 從字符串的末尾開始查找字符
    cout << s.rfind('i') << endl;             // 結果是:18-------因爲是從末尾開始查找,所以返回第一次找到的字符

    // 5. 在該字符串中查找第一個屬於字符串s的字符
    cout << s.find_first_of("13br98") << endl;  // 結果是:4---b

    // 6. 在該字符串中查找第一個不屬於字符串s的字符------先匹配dog,然後bird匹配不到,所以打印4
    cout << s.find_first_not_of("hello dog 2006") << endl; // 結果是:4
    cout << s.find_first_not_of("dog bird 2006") << endl;  // 結果是:9

    // 7. 在該字符串最後中查找第一個屬於字符串s的字符
    cout << s.find_last_of("13r98") << endl;               // 結果是:19

    // 8. 在該字符串最後中查找第一個不屬於字符串s的字符------先匹配t--a---c,然後空格匹配不到,所以打印21
    cout << s.find_last_not_of("teac") << endl;            // 結果是:21

}

(6)string的分割/截取字符串:strtok() & substr()

strtok();:分割字符串

void test10()
{
    char str[] = "I,am,a,student; hello world!";

    const char *split = ",; !";
    char *p2 = strtok(str,split);
    while( p2 != NULL )
    {
        cout<<p2<<endl;
        p2 = strtok(NULL,split);
    }
}

substr();

void test11()
{
    string s1("0123456789");
    string s2 = s1.substr(2,5); // 結果:23456-----參數5表示:截取的字符串的長度
    cout<<s2<<endl;
}

(7)string的字符替換:replace算法

replace函數包含於頭文件#include<string>中。

    /*用法一: 
     *用str替換指定字符串從起始位置pos開始長度爲len的字符 
     *string& replace (size_t pos, size_t len, const string& str); 
     */  
    int main()  
    {  
        string line = "this@ is@ a test string!";  
        line = line.replace(line.find("@"), 1, ""); //從第一個@位置替換第一個@爲空  
        cout << line << endl;     
        return 0;  
    }  

運行結果:
在這裏插入圖片描述
2.

    /*用法二: 
     *用str替換 迭代器起始位置 和 結束位置 的字符 
     *string& replace (const_iterator i1, const_iterator i2, const string& str); 
     */  
    int main()  
    {  
        string line = "this@ is@ a test string!";  
        line = line.replace(line.begin(), line.begin()+6, "");  //用str替換從begin位置開始的6個字符  
        cout << line << endl;     
        return 0;  
    }  
 

運行結果:
在這裏插入圖片描述
3.

    /*用法三: 
     *用substr的指定子串(給定起始位置和長度)替換從指定位置上的字符串 
     *string& replace (size_t pos, size_t len, const string& str, size_t subpos, size_t sublen); 
     */  
    int main()  
    {  
        string line = "this@ is@ a test string!";  
        string substr = "12345";  
        line = line.replace(0, 5, substr, substr.find("1"), 3); //用substr的指定子串(從1位置數共3個字符)替換從0到5位置上的line  
        cout << line << endl;     
        return 0;  
    }  

運行結果:
在這裏插入圖片描述
4.

/*用法八: 
 *用重複n次的c字符替換從指定位置pos長度爲len的內容 
 *string& replace (size_t pos, size_t len, size_t n, char c); 
 */  
int main()  
{  
    string line = "this@ is@ a test string!";  
    char c = '1';  
    line = line.replace(0, 9, 3, c);    //用重複3次的c字符替換從指定位置0長度爲9的內容  
    cout << line << endl;     
    return 0;  
}

運行結果:
在這裏插入圖片描述
5.

/*用法九: 
 *用重複n次的c字符替換從指定迭代器位置(從i1開始到結束)的內容 
 *string& replace (const_iterator i1, const_iterator i2, size_t n, char c); 
 */  
int main()  
{  
    string line = "this@ is@ a test string!";  
    char c = '1';  
    line = line.replace(line.begin(), line.begin()+9, 3, c);    //用重複3次的c字符替換從指定迭代器位置的內容  
    cout << line << endl;     
    return 0;  
}

運行結果:
在這裏插入圖片描述

注:所有使用迭代器類型的參數不限於string類型,可以爲vector、list等其他類型迭代器。

來源(一共九種)

九.STL標準模板庫

(1)for_each()函數

可將代碼:

vector<Review>::iterator pr;
    for(pr=book.begin();pr!=book.end();pr++)
        ShowReview(*pr);

替換爲:

 for_each(book.begin(),book.end(),ShowReview);
 

(2)random_shuffle()函數,隨機重新排序

STL中的函數random_shuffle()用來對一個元素序列進行重新排序(隨機的),函數原型如下:

template<class RandomAccessIterator>
   void random_shuffle(
      RandomAccessIterator _First, //指向序列首元素的迭代器
      RandomAccessIterator _Last  //指向序列最後一個元素的下一個位置的迭代器
   );
#include <bits/stdc++.h>
using namespace std;

int main()
{
    char b[]="abcde";
    char a[10];
    cout<<"char:"<<endl;
    for(int i=0;i<10;i++)
    {
        strcpy(a,b);
        random_shuffle(a,a+5);
        cout<<a<<endl;
    }

    int c[]={1,2,3,4,5};
    int d[10];
    cout<<endl<<"int:"<<endl;
    for(int i=0;i<10;i++)
    {
        memcpy(d,c,sizeof(c));
        random_shuffle(d,d+5);
        for(int j=0;j<5;j++) cout<<d[j]<<" ";
        cout<<endl;
    }
}

輸出:
在這裏插入圖片描述

(3)STL算法

函數庫對數據類型的選擇對其可重用性起着至關重要的作用。舉例來說,一個求方根的函數,在使用浮點數作爲其參數類型的情況下的可重用性肯定比使用整型作爲它的參數類性要高。而C++通過模板的機制允許推遲對某些類型的選擇,直到真正想使用模板或者說對模板進行特化的時候,STL就利用了這一點提供了相當多的有用算法。它是在一個有效的框架中完成這些算法的——你可以將所有的類型劃分爲少數的幾類,然後就可以在模版的參數中使用一種類型替換掉同一種類中的其他類型。
STL提供了大約100個實現算法的模版函數,比如算法for_each將爲指定序列中的每一個元素調用指定的函數,stable_sort以你所指定的規則對序列進行穩定性排序等等。只要我們熟悉了STL之後,許多代碼可以被大大的化簡,只需要通過調用一兩個算法模板,就可以完成所需要的功能並大大地提升效率。算法部分主要由頭文件<algorithm><numeric><functional>組成。
<algorithm>是所有STL頭文件中最大的一個(儘管它很好理解),它是由一大堆模版函數組成的,可以認爲每個函數在很大程度上都是獨立的,其中常用到的功能範圍涉及到比較、交換、查找、遍歷操作、複製、修改、移除、反轉、排序、合併等等。
<numeric>體積很小,只包括幾個在序列上面進行簡單數學運算的模板函數,包括加法和乘法在序列上的一些操作。
<functional>中則定義了一些模板類,用以聲明函數對象。
STL中算法大致分爲四類:

  • 非可變序列算法:指不直接修改其所操作的容器內容的算法。
  • 可變序列算法:指可以修改它們所操作的容器內容的算法。
  • 排序算法:對序列進行排序和合並的算法、搜索算法以及有序序列上的集合操作。
  • 數值算法:對容器內容進行數值計算。

C++ 各種迭代器
InputIterator是用於輸入的Iterator
OutputIterator是用於輸出的Iterator
ForwardIterator是InputIterator,同時可以保證++運算不會使之失效
RandomIteratorForwardIterator,同時具有+,-,+=,-=等運算及各種比較操作

以下對所有算法進行細緻分類並標明功能:

1.查找算法(13個):判斷容器中是否包含某個值

adjacent_find:

在iterator對標識元素範圍內,查找一對相鄰重複元素,找到則返回指向這對元素的第一個元素的ForwardIterator。否則返回last。重載版本使用輸入的二元操作符代替相等的判斷。

binary_search:

在有序序列中查找value,找到返回true。重載的版本實用指定的比較函數對象或函數指針來判斷相等。

count:

利用等於操作符,把標誌範圍內的元素與輸入值比較,返回相等元素個數。

count_if:

利用輸入的操作符,對標誌範圍內的元素進行操作,返回結果爲true的個數。

equal_range:

功能類似equal,返回一對iterator,第一個表示lower_bound,第二個表示upper_bound。

find:

利用底層元素的等於操作符,對指定範圍內的元素與輸入值進行比較。當匹配時,結束搜索,返回該元素的一個InputIterator。

find_end:

在指定範圍內查找"由輸入的另外一對iterator標誌的第二個序列"的最後一次出現。找到則返回最後一對的第一個ForwardIterator,否則返回輸入的"另外一對"的第一個ForwardIterator。重載版本使用用戶輸入的操作符代替等於操作。

find_first_of:

在指定範圍內查找"由輸入的另外一對iterator標誌的第二個序列"中任意一個元素的第一次出現。重載版本中使用了用戶自定義操作符。

find_if:

使用輸入的函數代替等於操作符執行find。

lower_bound:

返回一個ForwardIterator,指向在有序序列範圍內的可以插入指定值而不破壞容器順序的第一個位置。重載函數使用自定義比較操作。

upper_bound:

返回一個ForwardIterator,指向在有序序列範圍內插入value而不破壞容器順序的最後一個位置,該位置標誌一個大於value的值。重載函數使用自定義比較操作。

search:

給出兩個範圍,返回一個ForwardIterator,查找成功指向第一個範圍內第一次出現子序列(第二個範圍)的位置,查找失敗指向last1。重載版本使用自定義的比較操作。

search_n:

在指定範圍內查找val出現n次的子序列。重載版本使用自定義的比較操作。

2.排序和通用算法(14個):提供元素排序策略

inplace_merge:

合併兩個有序序列,結果序列覆蓋兩端範圍。重載版本使用輸入的操作進行排序。

merge:

合併兩個有序序列,存放到另一個序列。重載版本使用自定義的比較。

nth_element:

將範圍內的序列重新排序,使所有小於第n個元素的元素都出現在它前面,而大於它的都出現在後面。重載版本使用自定義的比較操作。

partial_sort:

對序列做部分排序,被排序元素個數正好可以被放到範圍內。重載版本使用自定義的比較操作。

partial_sort_copy:

partial_sort類似,不過將經過排序的序列複製到另一個容器。

partition:

對指定範圍內元素重新排序,使用輸入的函數,把結果爲true的元素放在結果爲false的元素之前。

random_shuffle:

對指定範圍內的元素隨機調整次序。重載版本輸入一個隨機數產生操作。

reverse:

將指定範圍內元素重新反序排序。

reverse_copy:

與reverse類似,不過將結果寫入另一個容器。

rotate:

將指定範圍內元素移到容器末尾,由middle指向的元素成爲容器第一個元素。

rotate_copy:

與rotate類似,不過將結果寫入另一個容器。

sort:

以升序重新排列指定範圍內的元素。重載版本使用自定義的比較操作。

stable_sort:

與sort類似,不過保留相等元素之間的順序關係。

stable_partition:

與partition類似,不過不保證保留容器中的相對順序。

3.刪除和替換算法(15個)

copy:

複製序列

copy_backward:

copy相同,不過元素是以相反順序被拷貝。

iter_swap:

交換兩個ForwardIterator的值。

remove:

刪除指定範圍內所有等於指定元素的元素。注意,該函數不是真正刪除函數。內置函數不適合使用removeremove_if函數。

remove_copy:

將所有不匹配元素複製到一個制定容器,返回OutputIterator指向被拷貝的末元素的下一個位置。

remove_if:

刪除指定範圍內輸入操作結果爲true的所有元素。

remove_copy_if:

將所有不匹配元素拷貝到一個指定容器。

replace:

將指定範圍內所有等於vold的元素都用vnew代替。

replace_copy:

與replace類似,不過將結果寫入另一個容器。

replace_if:

將指定範圍內所有操作結果爲true的元素用新值代替。

replace_copy_if:

replace_if,不過將結果寫入另一個容器。

swap:

交換存儲在兩個對象中的值。

swap_range:

將指定範圍內的元素與另一個序列元素值進行交換。

unique:

清除序列中重複元素,和remove類似,它也不能真正刪除元素。重載版本使用自定義比較操作。

unique_copy:

與unique類似,不過把結果輸出到另一個容器。

4.排列組合算法(2個):提供計算給定集合按一定順序的所有可能排列組合

next_permutation:

取出當前範圍內的排列,並重新排序爲下一個排列。重載版本使用自定義的比較操作。

prev_permutation:

取出指定範圍內的序列並將它重新排序爲上一個序列。如果不存在上一個序列則返回false。重載版本使用自定義的比較操作。

5.算術算法(4個)

accumulate:

iterator對標識的序列段元素之和,加到一個由val指定的初始值上。重載版本不再做加法,而是傳進來的 二元操作符被應用到元素上。

partial_sum:

創建一個新序列,其中每個元素值代表指定範圍內該位置前所有元素之和。重載版本使用自定義操作代替加法。

inner_product:

對兩個序列做內積(對應元素相乘,再求和)並將內積加到一個輸入的初始值上。重載版本使用用戶定義的操作。

adjacent_difference:

創建一個新序列,新序列中每個新值代表當前元素與上一個元素的差。重載版本用指定二元操作計算相鄰元素的差。

7.生成和異變算法(6個)

fill:

將輸入值賦給標誌範圍內的所有元素。

fill_n:

將輸入值賦給first到first+n範圍內的所有元素。

for_each:

用指定函數依次對指定範圍內所有元素進行迭代訪問,返回所指定的函數類型。該函數不得修改序列中的元素。

generate:

連續調用輸入的函數來填充指定的範圍。

generate_n:

與generate函數類似,填充從指定iterator開始的n個元素。

transform:

將輸入的操作作用與指定範圍內的每個元素,併產生一個新的序列。重載版本將操作作用在一對元素上,另外一個元素來自輸入的另外一個序列。結果輸出到指定容器。

7.關係算法(8個)

equal:

如果兩個序列在標誌範圍內元素都相等,返回true。重載版本使用輸入的操作符代替默認的等於操作符。

includes:

判斷第一個指定範圍內的所有元素是否都被第二個範圍包含,使用底層元素的<操作符,成功返回true。重載版本使用用戶輸入的函數。

lexicographical_compare:

比較兩個序列。重載版本使用用戶自定義比較操作。max: 返回兩個元素中較大一個。重載版本使用自定義比較操作。max_element: 返回一個ForwardIterator,指出序列中最大的元素。重載版本使用自定義比較操作。

min:

返回兩個元素中較小一個。重載版本使用自定義比較操作。

min_element:

返回一個ForwardIterator,指出序列中最小的元素。重載版本使用自定義比較操作。

mismatch:

並行比較兩個序列,指出第一個不匹配的位置,返回一對iterator,標誌第一個不匹配元素位置.如果都匹配,返回每個容器的last。重載版本使用自定義的比較操作。

8.集合算法(4個)

set_union:

構造一個有序序列,包含兩個序列中所有的不重複元素。重載版本使用自定義的比較操作。

set_intersection:

構造一個有序序列,其中元素在兩個序列中都存在。重載版本使用自定義的比較操作。

set_difference:

構造一個有序序列,該序列僅保留第一個序列中存在的而第二個中不存在的元素。重載版本使用自定義的比較操作。

set_symmetric_difference:

構造一個有序序列,該序列取兩個序列的對稱差集(並集-交集)。

9.堆算法(4個)

make_heap:

把指定範圍內的元素生成一個堆。重載版本使用自定義比較操作。

pop_heap:

並不真正把最大元素從堆中彈出,而是重新排序堆。它把first和last-1交換,然後重新生成一個堆。可使用容器的back來訪問被"彈出"的元素或者使用pop_back進行真正的刪除。重載版本使用自定義的比較操作。

push_heap:

假設first到last-1是一個有效堆,要被加入到堆的元素存放在位置last-1,重新生成堆。在指向該函數前,必須先把元素插入容器後。重載版本使用指定的比較操作。

sort_heap:

對指定範圍內的序列重新排序,它假設該序列是個有序堆。重載版本使用自定義比較操作。

(4)仿函數

【C++ STL】深入解析神祕的 — 仿函數

C++中STL用法超詳細總結

注:如果您通過本文,有(qi)用(guai)的知識增加了,請您點個贊再離開,如果不嫌棄的話,點個關注再走吧,日更博主每天在線答疑 ! 當然,也非常歡迎您能在討論區指出此文的不足處,作者會及時對文章加以修正 !如果有任何問題,歡迎評論,非常樂意爲您解答!( •̀ ω •́ )✧

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章