C 語言跟 C++ 的差異比較
C++ 完整的 CHM 版離線手冊,可以 從這裡下載。
C++標頭檔案不必是 .h 結尾
C語言中的標準庫標頭檔案,例如 math.h 和 stdio.h,在C++中被命名為 cmath 和 cstdio:
#include <cmath>
#include <cstdio>
int main() {
double a = 1.2;
a = sin(a);
printf("%lf\n", a);
}
名稱空間 namespace
為了防止重名,通過 ::
運算子決定某個名字屬於哪個名稱空間。不加限定時,表示使用全域性名稱空間。
標準庫中的名字,屬於標準名稱空間 std,例如 using std::cout
通常有三種方法使用名稱空間中的某個名字:
using namespace XX; // 引入整個名稱空間
using XX::name; // 引入單個名字
XX::name; // 程式中直接通過名稱空間使用其中的名字
#include <cstdio> namespace first { int a; void f(){} int g(){return 666;} } namespace second { double a; double f(){return 3.14;} char g; } int main() { first::a = 2; second::a = 3.14; first::a = first::g() + second::f(); second::a = first::g() + 1.23; printf("%d\n", first::a); printf("%lf\n", second::a); return 0; }
輸入輸出流
C++ 中,輸入輸出都是流,通過輸入輸出流庫(標頭檔案 iostream),使用輸出運算子 <<
和 輸入運算子 >>
進行輸入輸出。
- cout :標準輸出流物件(螢幕)
- cin:標準輸入流物件(鍵盤)
#include <iostream> using namespace std; int main() { double a; cout << "輸入一個浮點數,回車結束" << std::endl; // endl表示換行符,同時強制輸出 std::cin >> a; // 從標準輸入流獲取輸入,並存入 a cout << a * a; return 0; }
引用型別
C語言中的變數都是值型別,每個變數對應一塊記憶體。C++中引入了“引用型別”,引用型別的變數相當於一個具體的變數的“別名”。
指標 pointer 和引用 reference 的區別
- 指標是一個變數,只不過這個變數中存放的是一個地址,指向另一個記憶體單元。而引用跟原來的變數是同一個東西,只不過是原變數的別名。例如:
int a = 1; int *b = &a; // 指標b存放a變數的記憶體地址
int a = 1; int &b = a; // 引用b跟a是同一個東西,在記憶體中佔同一個儲存單元
- 指標可以有多級(存在 int **p),但引用只能有一級(不存在 int &&b)
- 可以有空指標,但是引用的值不能為NULL,且引用在定義的時候必須初始化
- 指標的值在初始化後可以改變,從而指向其他記憶體單元,但引用在初始化後就不能改變
- sizeof(指標) 得到指標本身的大小,sizeof(引用)得到所指向的變數或物件的大小
引用跟原變數指向同一塊記憶體空間:
#include <iostream>
using namespace std;
int main() {
double a = 3.14;
double &b = a; // 此時沒有為b分配記憶體空間,b跟a指向同一塊記憶體空間
b = 666;
cout << "a now is :" << a << endl;
return 0;
}
可以通過引用進行引數傳遞:
#include<iostream>
using namespace std;
void test(int &x) { // 此時沒有建立形參x,而是將x看做是實參的別名,x跟實參指向同一塊記憶體空間
cout<<&x<<" "<<x<<endl;
}
int main(void) {
int a=1;
cout<<&a<<" "<<a<<endl;
test(a);
return 0;
}
C跟C++中都可以使用指標
#include <iostream>
using namespace std;
void swap(int *x, int *y) {
int t = *x;
*x = *y, *y = t;
}
int main() {
int a = 1, b = 666;
swap(&a, &b);
cout << a << " " << b << endl;
return 0;
}
可以通過 const 修飾符防止通過引用修改原變數
使用引用可以減少記憶體的拷貝,當物件較大時可以提高效率。為了防止使用引用後,無意中修改了原物件,可以通過 const int &x
的形式來限定:
#include <iostream>
using namespace std;
void change(int &x, const int &y, int z) {
x = 666;
y = 667; // error: assignment of read-only reference 'y'
z = 668;
}
int main() {
int a = 1, b = 2, c;
change(a, b, c);
cout << a << " " << b << " " << c << endl;
return 0;
}
行內函數
用 inline
關鍵字宣告的函式稱為行內函數。編譯器碰到行內函數時,會用函式的程式碼替換這個函式,稱為“內斂展開”,從而避免了函式呼叫的開銷,提高程式執行效率。
#include <iostream>
#include <cmath>
using namespace std;
inline double area(double x, double y) {
return sqrt(x * x + y * y);
}
int main() {
double a = 3, b = 4;
cout << area(a, b) << endl;
return 0;
}
try-catch 異常處理機制
C++支援異常處理。異常事件發生時用 throw 關鍵字丟擲異常表示式,丟擲點稱為異常出現點,由作業系統為程式設定當前異常物件,然後執行異常處理程式碼,順序如下:
- 執行當前異常處理程式碼塊,依次匹配catch語句中的異常物件(只進行型別匹配)。
- 若匹配成功,則執行catch塊內的異常處理語句,然後接著執行try…catch…塊之後的程式碼。
- 如果在當前的try…catch…塊內找不到匹配該異常物件的catch語句,則由更外層的try…catch…塊來處理該異常。
- 如果當前函式內所有的try…catch…塊都不能匹配該異常,則遞歸回退到呼叫棧的上一層去處理該異常。
- 如果一直到主函式main()都不能處理該異常,則呼叫系統函式terminate()終止程式。
#include <iostream>
using namespace std;
int main() {
int score = 0;
try {
cin >> score;
if (socre > 100 || score < 0) throw score;
cout << "分數儲存成功“;
} catch (int score) {
cerr << "請輸入 0 - 100 之間的分數" << endl;
}
}
預設形參
C++ 中,函式的引數可以帶預設值,帶預設值的引數必須放在最右邊:
void test(int a, int b = 10, int c = 20) {...}
函式過載
C++ 中允許函式重名,只要形參不一樣(個數或型別不一樣)。呼叫函式時會根據實參和形參自動匹配最佳的函式。
#include <iostream>
using namespace std;
void test(int a, int b) {
cout << a + b << endl;
}
void test(int a, double b) {
cout << a + b << endl;
}
int main() {
test(3, 3.14);
test(3, 5);
return 0;
}
運算子過載
過載的運算子是帶有特殊名稱的函式,函式名是由關鍵字 operator 和其後要過載的運算子符號構成的。與其他函式一樣,過載運算子有一個返回型別和一個引數列表。
#include <iostream>
using namespace std;
struct Vector2{
double x;
double y;
};
Vector2 operator * (double a, Vector2 b) {
Vector2 r;
r.x = a * b.x;
r.y = a * b.y;
return r;
}
int main() {
Vector2 b, k;
b.x = 3.14;
b.y = 6.66;
k = 3.14 * b;
cout << k.x << endl;
}
template 模板
C++ 是強型別的語言,函式或類需要針對每一種具體型別進行操作時,程式碼大量冗餘。通過模板類或模板函式,可以編寫不針對某一具體型別的程式碼,編譯器在編譯時,可以針對具體資料型別,自動用模板函式生成針對該具體資料型別的函式或類。
模板函式
模板是泛型程式設計的基礎,泛型程式設計即以一種獨立於任何特定型別的方式編寫程式碼。
模板是建立泛型類或函式的藍圖。庫容器比如迭代器和演算法,都是泛型程式設計的例子,使用了模板的概念。
每個容器都有一個單一的定義,比如 向量,我們可以定義許多不同型別的向量,比如 vector 或 vector 。
模板函式定義如下,其中 type 是函式所使用的資料型別的佔位符名稱。這個名稱可以在函式定義中使用:
template <class type> ret-type func-name(parameter list)
{
// 函式主體
}
求不同資料型別最小值的模板函式:
#include <iostream>
using namespace std;
template <class T>
T minVal(T a, T b) {
return a > b ? b : a;
}
int main() {
int a = 3, b = 4;
cout << "min of int is: " << minVal(a, b) << endl;
double x = 3.14, y = 666;
cout << "min of double is: " << minVal(x, y) << endl;
}
上面例子中,當兩個數的型別也不同時,編譯時會報錯。要增加對不同型別資料的比較功能,需要改寫一下:
#include <iostream>
using namespace std;
template <class T, class U>
T minVal(T a, U b) {
return a > b ? b : a;
}
int main() {
int a = 3, b = 4;
cout << "min of int is: " << minVal(a, b) << endl;
double x = 3.14, y = 666;
cout << "min of double is: " << minVal(x, y) << endl;
cout << "min of mix is: " << minVal(a, y) << endl;
}
動態記憶體分配
C語言中通過 malloc/alloc/realloc 和 free 分配和釋放記憶體(在堆儲存區)。C++ 則通過 new 和delete 進行,會自動呼叫建構函式和解構函式。
#include <iostream>
#include <cstring>
using namespace std;
int main() {
double d = 3.14;
double *p = &d;
cout << *p << " " << p << endl;
p = new double;
*p = 3.1415926;
cout << *p << " " << p << endl;
delete p;
p = new double[4];
p[0] = 6.66;
p[1] = 7.77;
cout << p[0] << " " << *(p+1) << endl;
delete[] p;
char *s = new char[100];
strcpy(s, "hello world");
cout << s << endl;
}
struct 類定義
C++ 的 struct 中支援成員函式和成員變數
// class templates
#include <iostream>
using namespace std;
struct Date {
int y, m, d;
void print() {
cout << y << "-" << m << "-" << d << endl;
}
void init(int yy, int mm, int dd) {
y = yy; m = mm; d = dd;
}
};
int main () {
Date date;
date.y = 2000;
date.print();
date.init(2000, 8, 15);
date.print();
return 0;
}
this 指標
在類中可以使用 this 指標來表示類本身。
#include <iostream>
using namespace std;
struct Date {
int y, m, d;
void print() {
cout << y << "-" << m << "-" << d << endl;
}
void init(int yy, int mm, int dd) {
y = yy; m = mm; d = dd;
}
Date& add(int a) {
d += a;
return *this;
}
};
int main () {
Date date;
date.init(2000, 8, 15);
date.print();
date.add(3).add(5);
date.print();
return 0;
}
建構函式
C++ 的類中,與類名同名,且沒有返回值的函式就是建構函式。函式初始化時會首先自動呼叫建構函式。
不需要任何引數的建構函式稱為預設建構函式。如果沒有定義任何建構函式,則編譯器會自動生成預設建構函式。只要定義了自己的建構函式,則不再存在預設建構函式,如果需要,必須自己定義。
#include <iostream>
using namespace std;
struct Date {
int y, m, d;
void print() {
cout << y << "-" << m << "-" << d << endl;
}
Date() {
y = 2018; m = 1; d = 1;
}
Date(int yy, int mm, int dd) {
y = yy; m = mm; d = dd;
}
Date& add(int a) {
d += a;
return *this;
}
};
int main () {
Date date1;
date1.print();
Date date(2000, 8, 15);
date.print();
date.add(3).add(5);
date.print();
return 0;
}
建構函式中,可以使用預設值:
#include <iostream>
#include <cstring>
using namespace std;
struct Student {
int age;
char * name;
Student(char * n = "no_name", int a = 18) {
// *name = *n;
int len = strlen(n);
name = new char[len + 1];
strcpy(name, n);
age = a;
}
};
int main () {
Student s1;
cout << s1.name << "\t" << s1.age << endl;
Student s2("lisi");
cout << s2.name << "\t" << s2.age << endl;
Student s3("zs", 33);
cout << s3.name << "\t" << s3.age << endl;
return 0;
}
解構函式
C++ 中,類的同名函式前加 virtual ~
表示是解構函式。解構函式在類銷燬前自動呼叫,用於執行清理任務(例如關閉開啟的檔案、網路,釋放記憶體等)。
#include <iostream>
#include <cstring>
using namespace std;
struct Student {
int age;
char * name;
Student(char * n = "no_name", int a = 18) {
// *name = *n;
int len = strlen(n);
name = new char[len + 1];
strcpy(name, n);
age = a;
}
virtual ~Student() {
cout << name << " destroctur" << endl;
delete[] name;
}
};
int main () {
Student s1;
cout << s1.name << "\t" << s1.age << endl;
Student s2("lisi");
cout << s2.name << "\t" << s2.age << endl;
Student s3("zs", 33);
cout << s3.name << "\t" << s3.age << endl;
return 0;
}
拷貝建構函式
定義類物件時,可以用同類型的已有物件進行初始化,此時編譯器會自動建立拷貝建構函式並呼叫。
#include <iostream>
#include <cstring>
using namespace std;
struct Student {
int age;
char * name;
Student(char * n = "no_name", int a = 18) {
int len = strlen(n);
name = new char[len + 1];
strcpy(name, n);
age = a;
}
virtual ~Student() {
cout << name << " destroctur" << endl;
delete[] name;
}
};
int main () {
Student s1;
Student s2(s1);
cout << s2.name << "\t" << s2.age << endl;
return 0;
}
也可以自己實現拷貝建構函式:
Student(const Student &s) {
name = new char[100];
strcpy(name, s.name);
age = s.age;
cout << "這是拷貝建構函式" << endl;
}
類的賦值
可以使用賦值運算子,將一個物件賦值給另一個物件。
#include <iostream>
#include <cstring>
using namespace std;
struct Student {
int age;
char * name;
Student(char * n = "no_name", int a = 18) {
int len = strlen(n);
name = new char[len + 1];
strcpy(name, n);
age = a;
}
virtual ~Student() {
cout << name << " destroctur" << endl;
delete[] name;
}
};
int main () {
Student s1;
Student s2 = s1;
cout << s2.name << "\t" << s2.age << endl;
return 0;
}
也可以自己實現賦值運算子:
Stuednt& operator = (const Student &s) {
name = new char[100];
strcpy(name, s.name);
age = s.age;
cout << “自己的賦值運算子" << endl;
return *this;
}
拷貝建構函式和賦值運算子的完整例子
#include <iostream>
#include <cstring>
using namespace std;
struct Student {
int age;
char * name;
Student(char * n = "no_name", int a = 18) {
int len = strlen(n);
name = new char[len + 1];
strcpy(name, n);
age = a;
}
virtual ~Student() {
cout << name << " destroctur" << endl;
delete[] name;
}
Student& operator = (const Student &s) {
name = new char[100];
strcpy(name, s.name);
age = s.age;
cout << "自己的賦值運算子" << endl;
return *this;
}
Student(const Student &s) {
name = new char[100];
strcpy(name, s.name);
age = s.age;
cout << "這是拷貝建構函式" << endl;
}
};
int main () {
Student s1;
Student s2(s1);
s2 = s1;
cout << s2.name << "\t" << s2.age << endl;
return 0;
}
輸出:
這是拷貝建構函式
自己的賦值運算子
no_name 18
no_name destroctur
no_name destroctur
類成員的訪問控制及介面訪問
C++ 的可見性限定符有3中:
名稱 | 可見性 |
---|---|
public | 所有地方都可以訪問 |
private | 僅類自身可以訪問 |
protect | 僅類及其子類可以訪問 |
通常,屬性不可以直接暴露在外部,而是通過介面來訪問(檢視或修改)。
在類的外部定義成員函式
C++要求使用前先宣告。如果把成員定義放到類宣告中,當類中的兩個定義互相呼叫時,那麼這兩個宣告無論誰先後,最先的那個總是使用到了未宣告的符號;如果把成員定義和類宣告分開,就可以在定義使用之前把所需的宣告全列出來。
類的成員函式,包括建構函式,都可以在類的外部定義(方法名前需要加 類名::
),但是需要在類的內部宣告。
#include <iostream>
#include <cstring>
using namespace std;
struct Student {
private:
int age;
char * name;
public:
Student(char * n = "no_name", int a = 18) {
int len = strlen(n);
name = new char[len + 1];
strcpy(name, n);
age = a;
}
virtual ~Student() {
delete[] name;
}
char * getName();
};
char * Student::getName() {
return name;
}
int main () {
Student s1("xiaoming");
// cout << s1.name << "\t" << s1.age << endl;
cout << s1.getName() << endl;
return 0;
}
類模板
參考 這裡
C++ 是強型別的語言。如果針對每種型別寫一個類,冗餘太高,所以有了類模板。
類模板是忽略具體型別的公共邏輯的抽象,通常用來作為容器(例如:vector)或者行為(例如:clonable)的封裝。最簡單的例子:
#include <iostream>
using namespace std;
template <class T>
class myT {
public:
T max(T a, T b) {
return a > b ? a : b;
}
};
int main() {
myT<int> m1;
cout << m1.max(1, 2) << endl;
return 0;
}
與模板函式不同,類模板不能推斷例項化。所以必須在例項化時顯式指定型別引數,例如:Printer<int> p(1)
,而不能讓編譯器自行推斷 Printer p(1)
。
#include <iostream>
using namespace std;
template <class T>
class mypair {
T a, b;
public:
mypair (T first, T second)
{a=first; b=second;}
T getmax ();
};
template <class T>
T mypair<T>::getmax ()
{
T retval;
retval = a>b? a : b;
return retval;
}
int main () {
mypair <int> myobject (100, 75);
cout << myobject.getmax();
return 0;
}
類型別名 typedef
typedef 用於為已有的型別建立別名。
typedef是定義了一種型別的新別名,#define 則是簡單的字串替換。
#include <iostream>
#include <typeinfo>
using namespace std;
typedef char * PCHAR; // 一般大寫
int main() {
char * p1, p2;
// p1 是字元指標型別,p2 是字元型別
cout << typeid(p1).name() << " " << typeid(p2).name() << endl;
PCHAR p3, p4;
// p3 p4 都是字元指標型別
cout << typeid(p3).name() << " " << typeid(p4).name() << endl;
return 0;
}
C++中的 string
C++ 支援 C 風格的字串(用 null 字元 ‘\0’ 終止的一維字元陣列),同時還引入了 string 類型別。
- C 風格:
可以引入 cstring 這個 C 語言的字串庫,使用 strcpy、strlen、strcat、strcmp 等方法:
#include <iostream>
using namespace std;
int main() {
char str[] = "hello world";
char str2[3] = "AB"; // 結束字元佔一個字元,所以這裡最多放兩個
cout << str << endl;
cout << str2 << endl;
cout << str[2] << endl;
return 0;
}
- String 類:
#include <iostream>
#include <string>
using namespace std;
int main() {
string str = "hello world";
cout << str << endl;
string str2("ABC");
cout << str2 << endl;
string str3(str);
cout << str3 << endl;
string str4(str.begin(), str.end()-2);
cout << str4 << endl;
string str5(str, 5);
cout << str5 << endl;
cout << str.size() << endl;
cout << str + str2 << endl;
}
輸出:
hello world
ABC
hello world
hello wor
world
11
hello worldABC
STL
STL:標準模板庫(Standard Template Library),是 C++ 內建支援的庫。STL 利用的 C++ 的類模板和函式模板機制,由容器、演算法和迭代器組成。
容器
容器::資料儲存上,有一種物件型別,它可以持有其他物件或指向其他物件的指標,這種物件型別叫容器。
容器就是儲存其他物件和相關方法的物件,是對特定程式碼重用問題的良好的解決方案。
STL 提供的容器有:
- 順序容器:線性表結構
- vector容器:從後面快速插入和刪除,訪問任一元素
- deque雙端陣列:從前後兩側快速插入和刪除,訪問任一元素
- list連結串列:從任何位置插入和刪除
- 關聯容器:二叉樹結構
- set容器:快速查詢,不允許重複值
- multiset容器:快速查詢,允許重複值
- map容器:一對多對映,基於關鍵字快速查詢,不允許重複值
- multimap容器:一對多對映,基於關鍵字快速查詢,允許重複值
- 容器介面卡:介面轉換
- stack棧模型:先進後出
- queue佇列模型:先進先出
- priotriy_queue優先順序佇列:最高優先順序的先出
Vector 容器
向量(Vector)是一個封裝了動態大小的陣列的順序容器(Sequence Container)。跟任意其它型別容器一樣,能夠存放各種型別的物件。可以簡單的認為,向量是一個能夠存放任意型別的動態陣列。
vector 在尾部新增或者移除元素非常快,中間元素的操作非常耗時,因為需要移動元素。
優缺點:
- 檢索效率高
- 操作最後一個元素效率高
- 操作中間元素效率差
- 一旦需要重新分配空間,則效能很差
相關函式
- 建構函式
vector():建立一個空vector
vector(int nSize):建立一個vector,元素個數為nSize
vector(int nSize,const t& t):建立一個vector,元素個數為nSize,且值均為t
vector(const vector&):拷貝建構函式
vector(begin,end):複製[begin,end)區間內另一個數組的元素到vector中
- 增刪元素
void push_back(const T& x):向量尾部增加一個元素X
iterator insert(iterator it,const T& x):向量中迭代器指向元素前增加一個元素x
iterator insert(iterator it,int n,const T& x):向量中迭代器指向元素前增加n個相同的元素x
iterator insert(iterator it,const_iterator first,const_iterator last):向量中迭代器指向元素前插入另一個相同型別向量的[first,last)間的資料
iterator erase(iterator it):刪除向量中迭代器指向元素
iterator erase(iterator first,iterator last):刪除向量中[first,last)中元素
void pop_back():刪除向量中最後一個元素
void clear():清空向量中所有元素
- 迭代
reference at(int pos):返回pos位置元素的引用,比 [] 陣列方式多了越界校驗
reference front():返回首元素的引用
reference back():返回尾元素的引用
iterator begin():返回向量頭指標,指向第一個元素
iterator end():返回向量尾指標,指向向量最後一個元素的下一個位置
reverse_iterator rbegin():反向迭代器,指向最後一個元素
reverse_iterator rend():反向迭代器,指向第一個元素之前的位置
- 其他
bool empty() const:判斷向量是否為空,若為空,則向量中無元素
int size() const:返回向量中元素的個數
int capacity() const:返回當前向量張紅所能容納的最大元素值
int max_size() const:返回最大可允許的vector元素數量值
void swap(vector&):交換兩個同類型向量的資料
void assign(int n,const T& x):設定向量中第n個元素的值為x
void assign(const_iterator first,const_iterator last):向量中[first,last)中元素設定成當前向量元素
示例
#include <vector>
#include <iostream>
#include <algorithm>
#include <stdexcept>
#include <iterator>
using namespace std;
int main(int argc, const char * argv[]) {
const int SIZE = 6;
int array[SIZE] = {1, 2, 3, 4, 5, 6};
vector<int> v(array, array + SIZE);
cout << "first element:" << v.front() << " last:" << v.back() << endl;
v[1] = 7;
v.at(2) = 8;
v.insert(v.begin() + 2, 18);
v.push_back(666); // weibu尾部zhuij尾部追加yuansu
vector<int>::iterator it;
it = v.begin();
while(it != v.end()) {
cout << *it << endl;
it++;
}
it = find(v.begin(), v.end(), 22);
if (it != v.end())
cout << "location is: " << (it - v.begin()) << endl;
else
cout << "not found" << endl;
cout << "max size is:" << v.max_size() << endl;
cout << "capacity is:" << v.capacity() << endl;
try {
v.at(666) = 777;
} catch (out_of_range & e) {
cout << "Exception: " << e.what() << endl;
}
v.erase(v.begin());
v.erase(v.begin(), v.end());
cout << (v.empty() ? "yes empty" : "not empty") << endl;
}
list 容器
list 容器是雙向線性連結串列結構,指標將所有元素連結起來。
優缺點:
- 檢索效率差,需要順序查詢,迭代器只能 ++,不能一次性跳轉
- 增刪元素效率高
相關函式
pop_back() 刪除最後一個元素
pop_front() 刪除第一個元素
push_back() 在list的末尾新增一個元素
push_front() 在list的頭部新增一個元素
示例
int main(int argc, const char * argv[]) {
list<int> l; //建立list物件
//尾部新增元素
for (int i = 0; i < 10; i++) {
l.push_back(i);
}
//頭部新增元素
l.push_front(111);
//刪除頭部元素
l.erase(l.begin());
//刪除某個區間
list<int>::iterator it = l.begin();
it++;
it++;
it++;
l.erase(l.begin(), it);
//移除值為100的所有元素
l.remove(100);
//遍歷
for (list<int>::iterator it = l.begin(); it != l.end(); it++) {
cout << *it << " ";
}
cout << endl;
return 0;
}
map 容器
stack 容器操作跟堆疊一樣,都支援入棧和出棧。
相關函式
insert() 插入元素
key_comp() 返回比較元素key的函式
lower_bound() 返回鍵值>=給定元素的第一個位置
示例
set 容器
set 是包含有序物件的關聯容器,預設的順序是從小到大的。
相關函式
count(): 返回某個值元素的個數
empty(): 如果集合為空,返回true
erase(): 刪除集合中的元素
insert(): 在集合中插入元素
max_size(): 返回集合能容納的元素的最大限值
size(): 集合中元素的數目
swap(): 交換兩個集合變數
value_comp(): 返回一個用於比較元素間的值的函式
示例
void main()
{
//預設,從小到大
set<int> set1;
set<int, less<int>> set2;
//從大到小
set<int, greater<int>> set3;
//新增元素
for (int i = 0; i < 5; i++) {
int tmp = rand();
set3.insert(tmp);
}
//遍歷
for (set<int>::iterator it = set3.begin(); it != set3.end(); it++) {
cout<< *it << " ";
}
}
deque 容器
deque 是一個雙端陣列容器,可以在頭部和尾部操作元素。
相關函式
void push_back(const T& x):deque尾部增加一個元素X
void pop_back():刪除deque中最後一個元素
void push_front(const T& x):deque頭部增加一個元素X
void pop_front():刪除deque中第一個元素
示例
stack 容器
stack 容器操作跟堆疊一樣,都支援入棧和出棧。
相關函式
empty() 堆疊為空則返回真
pop() 移除棧頂元素
push() 在棧頂增加元素
size() 返回棧中元素數目
top() 返回棧頂元素
示例
演算法
STL 包含一些獨立函式(稱為演算法)用來操作容器。需要引入 algorithm 標頭檔案後使用。
例如,find 查詢演算法,找到元素則返回元素的迭代器,否則返回改容器最後一個元素之後的位置(即 v.end()
)。copy 複製演算法,將容器或其一部分複製到另一個容器中。
迭代器
使用迭代器,可以對容器元素進行列舉遍歷。迭代器定義在 中。
迭代器相當於指標,可以進行解引用(求出指標所指向變數的值,*p)和算術運算。
迭代器的宣告
迭代器有4中不同宣告方式,第一種最常用:
iterator:前項遍歷,可讀可寫
const_iterator:前項遍歷,只讀
reverse_iterator:後向遍歷,可讀可寫
const_reverse_iterator:後向遍歷,只讀
迭代器函式
假設 v 是某個例項化的容器,例如 vector<int> v()
,則:
v.begin():返回指向容器首元素的迭代器
v.end():返回指向容器尾元素的下一個位置的迭代器
v.rbegin():返回指向容器最後一個元素的反向迭代器
v.rend():返回指向容器第一個元素之前的位置的反向迭代器