久久精品国产精品国产精品污,男人扒开添女人下部免费视频,一级国产69式性姿势免费视频,夜鲁夜鲁很鲁在线视频 视频,欧美丰满少妇一区二区三区,国产偷国产偷亚洲高清人乐享,中文 在线 日韩 亚洲 欧美,熟妇人妻无乱码中文字幕真矢织江,一区二区三区人妻制服国产

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

C++笔记汇总

發(fā)布時(shí)間:2024/1/1 c/c++ 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++笔记汇总 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

C++基礎(chǔ)

本文是在學(xué)習(xí)B站黑馬C++課程時(shí)記錄。另有部分知識(shí)點(diǎn)為海賊班胡船長(zhǎng)所教授。在此表達(dá)對(duì)他們的誠(chéng)摯的感謝。

1、C++的左值右值:

首先了解引用的概念:引用是一個(gè)變量,它引用其他變量的 內(nèi)存位置

int x = 34 ; int &IRef = x;

在代碼中,IRef 就是一個(gè)引用。在聲明中,引用是通 & 符號(hào)來修飾的。它出現(xiàn)在類型與變量的標(biāo)識(shí)符之間,這種類型的引用稱為左值引用。

左值:可以看作是一個(gè)關(guān)聯(lián)了名稱的內(nèi)存位置,允許程序的其他部分來訪問它。名稱:任何可用于訪問內(nèi)存位置的表達(dá)式。“指向指定的內(nèi)存,以變量形式存在” “相當(dāng)于容器”

右值:右值是一個(gè)臨時(shí)值,它不能被程序的其他部分訪問。“不指向任何地方” “相當(dāng)于容器內(nèi)的事物”

int x = 0; x = 5; x = sqrt(5);

x是一個(gè)左值,這是因?yàn)閤代表一個(gè)內(nèi)存位置,它可以被程序的其他部分訪問。

表達(dá)式sqrt(5)時(shí)一個(gè)右值,因?yàn)樗砹艘粋€(gè)由編譯器創(chuàng)建的臨時(shí)內(nèi)存位置,以保存由函數(shù)返回的值。該內(nèi)存位置僅被訪問一次。在此之后它就會(huì) 立即被刪除,再也不能被訪問。

C++11右值引用的概念:表示一個(gè)本應(yīng)該沒有名稱的臨時(shí)對(duì)象。右值引用的聲明與左值引用類似,但是它使用的是2個(gè)&符號(hào)&&。臨時(shí)對(duì)象最多可以有一個(gè)左值引用指向它。

int && rRef = sqrt(5); cout << rRedf

2、C++中常量的定義:

兩種形式:

  • 使用宏定義

    #define Day 7 // 注意不要加分號(hào)
  • 使用const修飾符

    const int Day = 7; // 注意要加分號(hào)
  • 3、實(shí)數(shù)

  • 小數(shù)默認(rèn)是 雙精度double類型,因此在設(shè)置float類型時(shí)候,常在數(shù)字末尾添加f

    float x = 3.14f;
  • 精度

    floatdouble
    字節(jié)47
    有效位數(shù)815~16
  • 科學(xué)計(jì)數(shù)法

    float f = 3e3
  • 4、sizeof()

    可以查看占用內(nèi)存空間

    5、字符

    字符要用單引號(hào)。字符占用1個(gè)字節(jié)

    轉(zhuǎn)意字符: \a 警報(bào) \t \n ? \"

    6、字符串

    C語(yǔ)言風(fēng)格:注意變量名后面加中括號(hào)[],要用雙引號(hào)。

    char 變量名[] = "...hellO"

    C++風(fēng)格string

    #include <string> String 變量名 = "hello world"

    7、布爾類型

    bool flag = true; //注意全小寫,與python不同 bool key = false;

    8、邏輯運(yùn)算符

    運(yùn)算符:

    非 ! , 與 && , 或 ||

    9、 程序流程結(jié)構(gòu)

    順序結(jié)構(gòu)、選擇結(jié)構(gòu)、循環(huán)結(jié)構(gòu)

    if語(yǔ)句:注意與python的不同,條件表達(dá)式在括號(hào)內(nèi),且不加:。

    三目運(yùn)算符: 返回值的可以是變量,即左值

    //條件表達(dá)式1?表達(dá)式2:表達(dá)式3 int a = 0; int b = 20; (a < b ? a: b) = 100; cout << a << b << endl;

    switch語(yǔ)句:注意在case后面使用break

    switch(表達(dá)式) {case 結(jié)果1: // 注意類型,如果“結(jié)果1”是整型,傳入字符型的會(huì)導(dǎo)致出錯(cuò)。cout<< "best" << endl; // 注意不加中括號(hào)break;case 結(jié)果2:cout<< "good" << endl;break;default:cout<< "bad" << endl;break; }

    優(yōu)點(diǎn):結(jié)構(gòu)清晰,執(zhí)行效率高

    缺點(diǎn):判斷時(shí)只能時(shí)整型或者字符型,不能判斷一個(gè)區(qū)間。

    for語(yǔ)句:循環(huán)。注意C++中基于范圍的for循環(huán)如何使用。

    while語(yǔ)句:循環(huán)

    do while語(yǔ)句:先執(zhí)行一次循環(huán)語(yǔ)句,然后再判斷循環(huán)條件

    10、關(guān)于數(shù)字的個(gè)位數(shù)、十位數(shù)計(jì)算

    案例描述:計(jì)算三位數(shù)字的個(gè)位、十位、百位數(shù)計(jì)算:

    int x = rand()%1000 + 1 int a, b, c; a = x % 10; b = x /10 % 10; //先出發(fā) 后取模 c = x /100;

    11、跳轉(zhuǎn)語(yǔ)句

    break, continue:跳出當(dāng)前循環(huán)

    goto語(yǔ)句:

    FLAG: //標(biāo)記定義 cout << "jump to here"<< endl; goto FLAG; //跳轉(zhuǎn)到FLAG位置

    12、數(shù)組

    數(shù)組定義的三種形式

  • 數(shù)據(jù)類型 數(shù)組名 [數(shù)組長(zhǎng)度];

  • 數(shù)據(jù)類型 數(shù)組名 [數(shù)組長(zhǎng)度] = {值1, 值2 ...};

  • 數(shù)據(jù)類型 數(shù)組名 [ ] = {值1, 值2 ...}

  • 數(shù)組的輸出:使用for循環(huán)進(jìn)行輸出。

    sizeof(arr):可以統(tǒng)計(jì)整個(gè)數(shù)組在內(nèi)存中的長(zhǎng)度

    數(shù)組名是一個(gè)常量不能進(jìn)行復(fù)制操作。

    13、 隨機(jī)數(shù)種子

    srand(1); int x = rand() % 100 + 1;

    C++ 函數(shù)

    1、函數(shù)的定義

    函數(shù)返回值 函數(shù)名 (參數(shù)列表){//函數(shù)體語(yǔ)句return 表達(dá)式; }

    值傳遞: 就是函數(shù)調(diào)用時(shí)實(shí)參將 數(shù)值 傳入給形參。如果形參發(fā)生改變,并不回影響實(shí)參。

    函數(shù)聲明:聲明可以有多次,定義只能有一次。

    2、函數(shù)的分文件編寫

    作用:讓代碼更清晰

  • 頭文件 .h 中寫 函數(shù) 的聲明

    頭文件中不能寫函數(shù)的定義,以防止重定義。

    但是頭文件中可以寫 的定義。

  • 在源文件 .cpp 或 .cc 中寫 函數(shù) 的定義

  • 正確理解頭文件:#include "***.h"頭文件不進(jìn)行編譯,而是在預(yù)編譯階段,將***.h的 內(nèi)容 拷貝到引用位置,然后進(jìn)行源文件的編譯。

    3、內(nèi)聯(lián)函數(shù) inline

    內(nèi)聯(lián)函數(shù)在聲明時(shí),使用關(guān)鍵字inline

    內(nèi)聯(lián)的意義:在編譯時(shí),讓編譯器用該部分語(yǔ)句去替換函數(shù)表達(dá)式,節(jié)省了形參傳遞。

    注意事項(xiàng)

  • 內(nèi)聯(lián)函數(shù)體內(nèi)不能有循環(huán)和switch語(yǔ)句
  • 其定義必須出現(xiàn)在其第一次被調(diào)用之前
  • 內(nèi)聯(lián)函數(shù)不用對(duì)異常接口聲明。
  • C++ 指針

    1、定義和使用指針

    // 數(shù)據(jù)類型 *指針變量名; int a = 10; int *p = &a; // 將a的地址復(fù)制給指針p cout <<"a的地址是:"<< &a << endl; cout <<"指針p是:" << p << endl; // 指針前加*, 代表解引用。 cout << "*p的值是:" << *p <<endl; *p = 1000; cout << "*p的值是:" << *p <<endl;

    2、指針的大小

    32位系統(tǒng):指針占4個(gè)字節(jié)空間大小。0x0000

    64位系統(tǒng):占8個(gè)字節(jié)空間大小

    3、空指針和野指針

    空指針nullptr:用來給指針變量進(jìn)行初始化。并且空指針是不可以訪問的。

    // 空指針的幾種形式 int *p = nullptr; int *p = 0; inr *p = NULL;

    野指針:指向沒有訪問權(quán)限的位置的指針。

    int *p = (int*)0x1100;

    4、const修飾指針

    const修飾指針的三種情況:

  • const修飾指針 — 常量指針
  • const修飾常量 — 指針常量
  • const即修飾指針,又修飾常量
  • 常量指針 — const int *指針名 又名 指向常量的指針

    特點(diǎn):指針的指向可以修改,但是指針指向的地址的值不可以修改。

    // 常量指針 int a = 10, b = 20; const int *p = &a; // 常量指針的定義 *p = &b; // 正確,指針的指向可以修改 *p = 100; // 錯(cuò)誤,指針指向的值不可以被修改

    指針常量 — int * const p

    特點(diǎn):指針的指向不可以修改,但是指針指向的值可以修改

    // 指針常量 int * const p = &a;

    const即修飾指針,又修飾常量

    const int* const p

    特點(diǎn):指針的指向和指針指向的值都不可以被修改

    5、指針和函數(shù)

    地址傳遞,可以修改實(shí)參。

    C++結(jié)構(gòu)體

    結(jié)構(gòu)體屬于用戶自定義的數(shù)據(jù)類型,允許用戶存儲(chǔ)不同的基礎(chǔ)數(shù)據(jù)類型。

    建議:將結(jié)構(gòu)體的定義放在頭文件中

    1、結(jié)構(gòu)體的定義和使用

    語(yǔ)法: struct 結(jié)構(gòu)體名 {結(jié)構(gòu)體成員列表};

    通過結(jié)構(gòu)體創(chuàng)建變量的方式有三種:

  • struct 結(jié)構(gòu)體名 變量名

  • struct 結(jié)構(gòu)體名 變量名 = {成員1值, 成員2值}

  • 定義結(jié)構(gòu)體時(shí)順便創(chuàng)建變量

  • struct關(guān)鍵字在創(chuàng)建變量時(shí)可以省略。

    #include<string> // 結(jié)構(gòu)體定義 // 創(chuàng)建學(xué)生數(shù)據(jù)類型:學(xué)生(姓名, 年齡,分?jǐn)?shù)) struct Student{// 成員列表string name;int age;int score; }s3; // 3 定義結(jié)構(gòu)體時(shí)順便創(chuàng)建變量 //另外注意結(jié)構(gòu)體后面要使用分號(hào)// 創(chuàng)建結(jié)構(gòu)體類型變量 int main(){// 1 struct 結(jié)構(gòu)體名 變量名struct Student s1; // struct關(guān)鍵字在創(chuàng)建變量時(shí)可以省略// 給s1屬性復(fù)制。通過點(diǎn)“.”操作符訪問結(jié)構(gòu)體變量中的屬性s1.name = "東七七";s1.age = 21;s2.score = 77;// 2 struct 結(jié)構(gòu)體名 變量名 = {成員1值, 成員2值}struct Student s2 = {"James", 34, 91} }

    2、結(jié)構(gòu)體數(shù)組

    作用: 將自定義的結(jié)構(gòu)體放入到數(shù)組中方便維護(hù)

    語(yǔ)法: struct 結(jié)構(gòu)體名 數(shù)組名[元素大小] = { {},...,{} };

    struct Student stuArray[10]={{"James", 34, 91},...}

    3、結(jié)構(gòu)體指針

    作用:通過指針訪問結(jié)構(gòu)體中的成員

    利用操作符 -> 可以通過結(jié)構(gòu)體指針訪問結(jié)構(gòu)體屬性

    struct Student *p = &s1; p->name = "Alike"; p->age = 42;

    4、 嵌套結(jié)構(gòu)體

    作用: 結(jié)構(gòu)體中的成員可以是另一個(gè)結(jié)構(gòu)體

    例如:每一個(gè)老師輔導(dǎo)一個(gè)學(xué)員, 一個(gè)老師的結(jié)構(gòu)體中,記錄一個(gè)學(xué)生的結(jié)構(gòu)體

    // 學(xué)生結(jié)構(gòu)體定義 struct Student{string name;int age;int score; } // 教師結(jié)構(gòu)體定義 struct Teacher{int id;string name;int age;struct Student stu; }

    5、結(jié)構(gòu)體做函數(shù)參數(shù)

    作用:將結(jié)構(gòu)體作為參數(shù)傳入

    傳遞方式: 值傳遞,地址傳遞

    // 值傳遞 void printStuInfo(Student stu){// 函數(shù)體 } // 地址傳遞 void printStuInfo_ptr(const Student *ptr){ //定義常量指針,使得ptr指向的值不可以被修改//函數(shù)體ptr->name; // 注意要用->訪問結(jié)構(gòu)體成員 }

    6、結(jié)構(gòu)體中const的使用

    作用:用const修飾防止被錯(cuò)誤修改

    void printStuInfo_ptr(const Student *ptr){//函數(shù)體 ptr->name; // 注意要用->訪問結(jié)構(gòu)體成員 }

    C++核心編程

    1、內(nèi)存分區(qū)模型

    C++程序在執(zhí)行時(shí), 將內(nèi)存大方向劃分為4個(gè)區(qū)域

  • 代碼區(qū):存放函數(shù)體的二進(jìn)制代碼,由操作系統(tǒng)進(jìn)行管理

  • 全局區(qū): 存放全局變量和靜態(tài)變量以及常量

  • 棧區(qū): 由編譯器自動(dòng)分配釋放,存放函數(shù)的參數(shù)值,局部變量等

  • 堆區(qū):由程序員分配和釋放,若程序員不釋放,程序結(jié)束時(shí)由操作系統(tǒng)回收

  • 內(nèi)存四區(qū)的意義

    不同區(qū)域存放的數(shù)據(jù),賦予不同的生命周期,給我們更大的靈活編程。

    程序運(yùn)行前

    在程序編譯后,生成了exe可執(zhí)行程序,未執(zhí)行該程序前分為兩個(gè)分區(qū)

    代碼區(qū)

    ? a. 存放CPU執(zhí)行的機(jī)器指令

    ? b. 代碼區(qū)是 共享 的,目的是對(duì)于頻繁被執(zhí)行的程序,只需要在內(nèi)存中有一份代碼即可

    ? c. 代碼區(qū)是 只讀 的,目的是防止程序意外地修改了它的指令

    全局區(qū)

    ? a. 存放全局變量(注意是在main函數(shù)之外定義的)和靜態(tài)變量

    ? b. 全局區(qū)還包含了常量區(qū)字符串常量其他常量也存放在此

    ? c. 該區(qū)域的數(shù)據(jù)在程序結(jié)束后由操作系統(tǒng)釋放

    ? d. 局部變量、const修飾的局部變量(局部常量) 不在全局區(qū),而在棧區(qū)

    // 查看局部變量和全局變量的地址 // 全局變量 int g_a = 10; int g_b = 10;int main(){int a = 10;int b = 10:// 打印地址會(huì)發(fā)現(xiàn), a、b的地址在一個(gè)區(qū)間內(nèi) g_a、g_b的地址在另一個(gè)區(qū)間內(nèi) }

    程序運(yùn)行后:

    棧區(qū)

    由編譯器自動(dòng)分配釋放,存放函數(shù)的參數(shù)值、局部變量等。

    注意事項(xiàng):不要返回局部變量的地址,棧區(qū)開辟的數(shù)據(jù)由編譯器自動(dòng)釋放。

    int * func() //形參數(shù)據(jù)也會(huì)放到棧區(qū) {int a = 10; // 棧區(qū)的數(shù)據(jù)在函數(shù)執(zhí)行完自動(dòng)釋放。return &a; // 有錯(cuò)誤,但能通過編譯。返回了局部變量地址。 } int main(){int *p = func(); //接收func()的地址cout << *p << endl; // 第一次沒問題,因?yàn)榫幾g器做了保留cout << *p << endl; // 第二次出現(xiàn)亂碼 }

    堆區(qū)

    由程序員分配釋放,若程序員不釋放,程序結(jié)束時(shí)由操作系統(tǒng)回收。

    在C++中主要利用new來開辟堆區(qū)內(nèi)存,利用delete釋放

    int *func(){// 利用new關(guān)鍵字 可以將數(shù)據(jù)開辟到堆區(qū)// 指針 本質(zhì)也是局部變量, 放在棧上,指針保存的數(shù)據(jù)時(shí)放在堆區(qū)int *p = new int(10);return p; // 返回10在堆區(qū)地址, 且該地址由程序員使用delete才能釋放或者程序結(jié)束釋放 } int main(){int *p = func();cout << *p << endl; }

    語(yǔ)法: new 數(shù)據(jù)類型

    返回值: new 返回時(shí)該數(shù)據(jù)類型的指針

    new(10): 創(chuàng)建int類型的元素, 10表示值, 釋放用delete

    new[10]: 在堆區(qū)開辟數(shù)組,10表示10個(gè)元素, 釋放用delete[]

    // 1. new 的基本語(yǔ)法 int * func(){int *p = new int(10); // new返回的是int的指針,指向新分配元素的位置,位置的值為10;return p; } delete p; // 2. 在堆區(qū)利用new開辟數(shù)組 int * func2(){int* arr =new int[10]; // 10代表數(shù)組有10個(gè)元素return arr } delete[] arr; // 釋放數(shù)組,需要加[]

    2、引用

    作用: 給變量起別名,注意數(shù)據(jù)要相同, 因?yàn)椴粫?huì)發(fā)生數(shù)據(jù)類型隱式轉(zhuǎn)換

    語(yǔ)法: 數(shù)據(jù)類型 &別名 = 原名;

    注意事項(xiàng)

  • 引用定義時(shí)必須進(jìn)行初始化

  • 引用一旦初始化綁定后,就不能改變綁定對(duì)象了。

  • int a = 10; int c = 11; int &b = a; int &b; // 錯(cuò)誤,引用在定義時(shí)必須進(jìn)行初始化 int &b = c; // 錯(cuò)誤, 重定義 int &d = 10; // 錯(cuò)誤, 引用必須引一塊合法的內(nèi)存空間 b = c; // 正確, 但是,是賦值操作 不是綁引用

    引用做函數(shù)參數(shù) :

    作用: 函數(shù)傳參時(shí),可以利用引用的技術(shù)讓形參修飾實(shí)參

    優(yōu)點(diǎn): 可以簡(jiǎn)化指針修改實(shí)參

    // 交換函數(shù) // 1、值傳遞 void swap(int a, int b) { int temp = a; a = b; b = temp; } // 2、地址傳遞 void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } // 3、引用傳遞 void swap(int &a, int &b) { int temp = a; a = b; b = temp; }

    引用做函數(shù)返回值 :

    作用: 引用是可以作為函數(shù)的返回值存在

    注意:不要返回局部變量的引用

    用法:函數(shù)的調(diào)用可以作為左值

    int& func(){static int a = 10; // 靜態(tài)變量,存放在全局區(qū),全局區(qū)上的數(shù)據(jù)在程序結(jié)束后系統(tǒng)釋放return a; } int p = func(); // 整個(gè)是復(fù)制操作, p的值與a相同,但是地址不同 int &r = func(); // r與a的值和地址都相同 func() = 1000; // 函數(shù)的調(diào)用作為左值。 過程: 返回靜態(tài)常量a的引用, 然后通過該引用修改a的值為1000。

    引用的本質(zhì) : 是一個(gè)指針常量。指針操作都由編譯器操作了。

    // 引用的本質(zhì) int &r = a; // 實(shí)際被自動(dòng)轉(zhuǎn)換為 int* const ref = &a; 指針常量是不可更改的,這也說明了為什么引用不可更改 r = 30; // 內(nèi)部發(fā)現(xiàn)r是引用,自動(dòng)轉(zhuǎn)換為 *ref = 20; 引用的值不是常量,所以可以更愛

    常量引用 :

    作用: 常量引用主要用來修飾形參,防止誤操作

    在函數(shù)形參列表中,可以加 const 修飾形參, 防止形參改變實(shí)參

    // 常量引用 int & ref = 10; // 錯(cuò)誤, 引用必須引用一塊合法的內(nèi)存空間 const int & ref = 10; // 正確 // 加入const之后,編譯器將代碼修改為 int temp = 10; const int & ref = temp; ref = 20; //錯(cuò)誤, 加入const之后變?yōu)橹蛔x,不可以修改// 打印數(shù)據(jù)的函數(shù) void showValue(const int & value){cout << value << endl; }

    3、函數(shù)提高(默認(rèn)、占位、重載)

    函數(shù)的默認(rèn)參數(shù)

    函數(shù)的形參列表中的形參是可以有默認(rèn)值的。

    語(yǔ)法: 返回值類型 函數(shù)名 (參數(shù)= 默認(rèn)值) { 函數(shù)體 }

    // 如果某個(gè)位置已經(jīng)有了默認(rèn)參數(shù),那么從這個(gè)位置往后,從左到右都必須有默認(rèn)值 int func(int a; int b = 1; int c =2){return 0; }

    注意:如果 函數(shù)聲明 有默認(rèn)參數(shù),函數(shù)定義不能 有默認(rèn)參數(shù)。因?yàn)闀?huì)出現(xiàn)重定義。

    函數(shù)的占位參數(shù)

    函數(shù)的形參列表里可以有占位參數(shù),用來做占位,調(diào)用函數(shù)時(shí)必須補(bǔ)充該位置。

    語(yǔ)法: 返回值類型 函數(shù)名 (數(shù)據(jù)類型) {函數(shù)體};

    // 占位參數(shù) void func(int a, int){ // 第二個(gè)參數(shù) 是占位參數(shù) return ; } // 調(diào)用 func(1,2); // 調(diào)用函數(shù)時(shí)必須補(bǔ)充該位置 // 占位參數(shù)可以有默認(rèn)參數(shù) void func2(int a, int = 10){ return ;}

    函數(shù)重載

    作用: 函數(shù)名可以相同,提高復(fù)用性

    函數(shù)重載滿足條件

  • 同一個(gè)作用域下

  • 函數(shù)名稱相同

  • 函數(shù)的 參數(shù)類型不同 或者 個(gè)數(shù)不同 或者 順序不同(需要是不同類型)。

  • 注意:函數(shù)的返回值 不可以作為函數(shù)重載的條件

    // 函數(shù)重載 void func(){// 函數(shù)體 } void func(int a){ // 函數(shù)體 } void func(int a, string b){// 函數(shù)體 } void func(string b, int a){// 函數(shù)體 }

    函數(shù)重載的注意事項(xiàng)

  • 引用作為重載條件
  • 函數(shù)重載遇到默認(rèn)參數(shù)
  • // 引用作為重載的條件 void func(int &a){ // 函數(shù)形式1 } void func(const int &a){ // 常量引用可以 整數(shù)常量等不可以// 函數(shù)形式2 } // 調(diào)用 int r = 10; func(r); // 調(diào)用形式1 const int p = 10; func(p); // 調(diào)用形式2 func(10); // 調(diào)用形式2 // 函數(shù)重載遇到默認(rèn)參數(shù) void func(int a){ // 函數(shù)形式1 } void func(int a, int b = 10){ // 使用默認(rèn)參數(shù)值 // 函數(shù)形式2 }func(10); // 調(diào)用func出錯(cuò), 形式1和形式2都能被調(diào)用, 盡量避免

    C++ 類和對(duì)象

    C++面向?qū)ο蟮奶匦?#xff1a;抽象、封裝、繼承、多態(tài)

    1、封裝

    作用:

  • 將屬性和行為作為一個(gè)整體,表現(xiàn)生活中的事物
  • 將屬性和行為加以權(quán)限限制
  • 語(yǔ)法:class 類名{ 訪問權(quán)限: 屬性 / 行為 };注意最后的分號(hào),默認(rèn)訪問權(quán)限是private。

    術(shù)語(yǔ):

  • 類中的屬性和行為 統(tǒng)稱為 成員
  • 屬性: 成員屬性 或 成員變量
  • 行為: 成員函數(shù) 或 成員方法
  • // 案例 1 // 設(shè)計(jì)一個(gè)圓類,求圓的周長(zhǎng) // 圓求周長(zhǎng)的公式 : 2 * PI * 半徑, 半徑作為一個(gè)屬性#include<iostream> using namespace std; const double PI = 3.14;class Circle {// 訪問權(quán)限 public:// 屬性int m_r;// 行為// 獲取圓的周長(zhǎng),常使用函數(shù)double calculateZC() {return 2 * PI * m_r;} };int main(){// 通過圓類來創(chuàng)建具體的圓Circle c1;// 給圓對(duì)象的屬性進(jìn)行復(fù)制, "."操作符c1.m_r = 10;cout << "圓的周長(zhǎng): " << c1.calculateZC() << endl;return 0; }

    三種訪問權(quán)限

    類內(nèi)類外
    public公共權(quán)限😀😀
    protected保護(hù)權(quán)限😀😈繼承時(shí),兒子可以訪問父親中的保護(hù)內(nèi)容
    private私有權(quán)限😀😈繼承時(shí),兒子不可以訪問父親中的私有內(nèi)容

    Struct 和 Class 的區(qū)別:

    唯一區(qū)別:默認(rèn)訪問權(quán)限不同

  • struct 默認(rèn)權(quán)限為公共
  • class 默認(rèn)權(quán)限為私有
  • 成員屬性設(shè)置為私有:

  • 可以自己控制讀寫權(quán)限(使用成員方法進(jìn)行控制,比如針對(duì)成員屬性設(shè)置訪問函數(shù))
  • 對(duì)于寫可以檢測(cè)數(shù)據(jù)的有效性
  • class Person{ public:void setName(string name){m_Name = name; // 內(nèi)部可以訪問到}int getAge(){return m_Age;} private:string m_Name;int m_Age;int M_Sex; };

    案例1:

    // 設(shè)計(jì)立方體類 // 屬性:長(zhǎng) 寬 高 // 行為:獲取立方體的面積 獲取立方體的體積 // 分別利用全局函數(shù)和成員函數(shù)判斷兩個(gè)立方體是否相等 #include<iostream> #include<string> using namespace std;class Cube { public:// 設(shè)置 長(zhǎng)void setL(int l) { m_L = l; }// 獲取 長(zhǎng)int getL() { return m_L; }// 設(shè)置 寬void setW(int w) { m_W = w; }// 獲取 寬int getW() { return m_W; }// 設(shè)置 高void setH(int h) { m_H = h; }// 獲取 高int getH() { return m_H; }// 獲取立方體的面積int getArea() {return 2 * (m_L * m_W + m_L * m_H + m_W * m_H);}// 獲取立方體的體積int getVolume() {return m_L * m_W * m_H;}// 判斷兩個(gè)立方體是否相等bool m_isSame(Cube& c2) {if (m_L == c2.getL() && m_W == c2.getW() && m_H == c2.getH())return true;return false;} private:int m_L; // 長(zhǎng)int m_W; // 寬int m_H; // 高 }; // 判斷兩個(gè)立方體是否相等 bool isSame(Cube& c1, Cube& c2) {if (c1.getL() == c2.getL() && c1.getW() == c2.getW() && c1.getH() == c2.getH())return true;return false; }int main(){Cube c1;c1.setL(10);c1.setW(10);c1.setH(10);cout << "c1的面積是:" << c1.getArea() << endl;cout << "c1的體積是:" << c1.getVolume() << endl;Cube c2;c2.setL(10);c2.setW(10);c2.setH(10);cout << "c1、c2是否相等:" << c1.m_isSame(c2) << endl;cout << "c1、c2是否相等:" << isSame(c1, c2) << endl;Cube c3;c3.setL(10);c3.setW(9);c3.setH(10);cout << "c1、c3是否相等:" << c1.m_isSame(c3) << endl;cout << "c1、c3是否相等:" << isSame(c1, c3) << endl;return 0; }

    案例2:

    #include<iostream> #include<string> using namespace std;class Point { public:void setX(int x) { m_x = x; }void setY(int y) { m_y = y; }int getX() { return m_x; }int getY() { return m_y; } private:int m_x;int m_y; };class Circle { public:void setR(int r) { m_r = r; }int getR() { return m_r; }void setCenter(Point center_point) { center = center_point; }Point getCenter() { return center; } private:int m_r;Point center; // 在圓的對(duì)象內(nèi)部使用了點(diǎn)Point對(duì)象來構(gòu)建圓心 }; int main() {Circle c1;Point center; // 圓心點(diǎn)center.setX(3);center.setY(4);c1.setR(9);c1.setCenter(center); }

    類的多文件結(jié)構(gòu):

    // 頭文件 Point.h #program once #include<iostram> using namespace std;// 僅使用類的聲明就可 class Point { public:void setX(int x) ;void setY(int y) ;int getX() ;int getY() ; private:int m_x;int m_y; }; // 源文件 Point.cpp 要使用 作用域限定符"::"來限定是Point類的成員函數(shù) #include "Point.h" void Point::setX(int x) { m_x = x; } void Point::setY(int y) { m_y = y; } int Point::getX() { return m_x; } int Point::getY() { return m_y; }

    2、對(duì)象的初始化和清理

    作用:C++中采用構(gòu)造函數(shù)和析構(gòu)函數(shù)來初始化對(duì)象和銷毀對(duì)象。

    2.1 構(gòu)造函數(shù)和析構(gòu)函數(shù)概念

    這兩個(gè)函數(shù)會(huì)被編譯器 自動(dòng)調(diào)用,完成對(duì)象的初始化和清理工作。對(duì)象的初始化和清理是編譯器強(qiáng)制要求我們做的事情,因此如果我們不提供構(gòu)造和析構(gòu),編譯器會(huì)提供編譯器提供的構(gòu)造函數(shù)和析構(gòu)函數(shù)是空實(shí)現(xiàn)

  • 析構(gòu)函數(shù):主要作用在于創(chuàng)建對(duì)象時(shí)為對(duì)象的成員屬性復(fù)制,構(gòu)造函數(shù)由編譯器自動(dòng)調(diào)用,無需手動(dòng)調(diào)用
  • 析構(gòu)函數(shù):主要作用在于對(duì)象銷毀前系統(tǒng)自動(dòng)調(diào)用,執(zhí)行一些清理工作。
  • 構(gòu)造函數(shù)的語(yǔ)法:類名(){}

  • 構(gòu)造函數(shù),沒有返回值也不寫void
  • 函數(shù)名稱與類名相同
  • 構(gòu)造函數(shù)可以有參數(shù),因此可以發(fā)生重載
  • 程序在調(diào)用對(duì)象時(shí)候會(huì)自動(dòng)調(diào)用構(gòu)造,無需手動(dòng)調(diào)用,而且只會(huì)調(diào)用一次。
  • 析構(gòu)函數(shù)的語(yǔ)法:~類名(){}

  • 析構(gòu)函數(shù),沒有返回值也不寫void
  • 函數(shù)名與類名相同,在名稱前加上符號(hào) ~
  • 析構(gòu)函數(shù) 不可以 有參數(shù),因此也不可以重載
  • 程序在對(duì)象銷毀前會(huì)自動(dòng)調(diào)用析構(gòu),無需手動(dòng)調(diào)用,而且只會(huì)調(diào)用一次
  • class Person{ public:Person(){ cout << "Person的構(gòu)造函數(shù)調(diào)用" << endl; }~Person(){ cout << "Person的析構(gòu)函數(shù)調(diào)用" << endl; } };

    2.2 構(gòu)造函數(shù)的分類及調(diào)用

    兩種分類方式:

    1. 按參數(shù)分為: 有參構(gòu)造和無參構(gòu)造(默認(rèn)構(gòu)造) 2. 按類型分類: 普通構(gòu)造和拷貝(復(fù)制)構(gòu)造(拷貝構(gòu)造也是一種構(gòu)造函數(shù),用戶沒有調(diào)用的話,編譯器會(huì)自動(dòng)聲成)

    三種調(diào)用方式:

  • 括號(hào)法
  • 顯示法
  • 隱含轉(zhuǎn)換法
  • #include<iostream> #include<string> using namespace std;class Person { public:Person() {cout << "Pereson的無參構(gòu)造函數(shù)調(diào)用" << endl;}Person(int a) {m_age = a;cout << "Pereson的有參構(gòu)造函數(shù)調(diào)用" << endl;}// 拷貝構(gòu)造函數(shù)Person(const Person& p) {// 將傳入的Person的屬性,拷貝到該對(duì)象m_age = p.m_age;} public:string m_name;int m_age; };// 調(diào)用 void test() {// 1、括號(hào)法Person p1; // 默認(rèn)構(gòu)造函數(shù)調(diào)用Person p2(5); // 有參構(gòu)造函數(shù)Person p3(p1);// 拷貝構(gòu)造函數(shù)// 注意事項(xiàng)// 調(diào)用默認(rèn)構(gòu)造函數(shù)時(shí),不要加(),即Person p1();// 因?yàn)榫幾g器會(huì)認(rèn)為是一個(gè)函數(shù)的聲明,不會(huì)認(rèn)為在創(chuàng)建對(duì)象// 2、顯示法Person p1;Person p2 = Person(10);Person P3 = Person(p2);Person(10); // 匿名對(duì)象 特點(diǎn):當(dāng)前行執(zhí)行結(jié)束后,系統(tǒng)會(huì)立即回收掉匿名對(duì)象// 注意事項(xiàng)2// 不要利用拷貝構(gòu)造函數(shù) 初始化匿名對(duì)象 "Person(p3);" 會(huì)報(bào)重定義錯(cuò)誤 // 編譯器會(huì)認(rèn)為 Person(p3) === Person p3// 3、隱式轉(zhuǎn)換法Person p4 = 10; // 相當(dāng)于 Person p4 = Person(10);Person p5 = p4; // 拷貝構(gòu)造}

    注意事項(xiàng) :

  • 調(diào)用默認(rèn)構(gòu)造函數(shù)時(shí),不要加()
  • 匿名對(duì)象,特點(diǎn):當(dāng)前行執(zhí)行結(jié)束后,系統(tǒng)會(huì)立即回收掉匿名對(duì)象
  • 不要利用拷貝構(gòu)造函數(shù)初始化匿名對(duì)象, 如Person(p3);
  • 2.3 拷貝構(gòu)造函數(shù)的調(diào)用時(shí)機(jī)

    C++拷貝構(gòu)造函數(shù)調(diào)用實(shí)際通常有三種情況:

  • 使用一個(gè)已經(jīng)創(chuàng)建完畢的對(duì)象來初始化一個(gè)新對(duì)象

    Person p2(p1);
  • 值傳遞方式給函數(shù)參數(shù)傳值

    void func(Person p){// 函數(shù)體 }
  • 以值方式返回局部對(duì)象

    Person func(){Person p1;return p1; }
  • ? 拷貝構(gòu)造函數(shù)的參數(shù)為什么是常量引用?

    2.4 構(gòu)造函數(shù)調(diào)用規(guī)則

    默認(rèn)情況下,C++編譯器至少給一個(gè)類添加3個(gè)函數(shù)

  • 默認(rèn)構(gòu)造函數(shù)(無參,函數(shù)體為空)
  • 默認(rèn)析構(gòu)函數(shù)(無參,函數(shù)體為空)
  • 默認(rèn)拷貝構(gòu)造函數(shù),對(duì)屬性進(jìn)行值拷貝。
  • 構(gòu)造函數(shù)調(diào)用規(guī)則如下:

  • 如果 用戶定義 有參構(gòu)造函數(shù)C++ 不再提供默認(rèn)無參構(gòu)造,但是會(huì)提供默認(rèn)拷貝構(gòu)造函數(shù)
  • 如果用戶定義拷貝構(gòu)造函數(shù), C++ 不會(huì)再提供其他構(gòu)造函數(shù)。
  • 可以使用類名()= default;來指示編譯器提供默認(rèn)無參構(gòu)造函數(shù)
  • 2.5 深拷貝與淺拷貝(面試內(nèi)容)

    淺拷貝:簡(jiǎn)單的賦值拷貝操作。增加了一個(gè)指針,指向原來已經(jīng)存在的內(nèi)存。

    深拷貝:在堆區(qū)重新申請(qǐng)空間,進(jìn)行拷貝操作。增加了一個(gè)指針,并新開辟了一塊空間。

    問題:淺拷貝帶來的問題是堆區(qū)的內(nèi)存重復(fù)釋放

    解決方法**:自己實(shí)現(xiàn)拷貝構(gòu)造函數(shù)**,新開辟堆區(qū)空間,來解決淺拷貝帶來的問題。 即深拷貝

    如果屬性有在堆區(qū)開辟的,一定要自己提供拷貝構(gòu)造函數(shù),防止淺拷貝帶來的問題

    (理解時(shí)可以寫程序逐語(yǔ)句F11調(diào)試一下)

    深拷貝: 當(dāng)被復(fù)制的對(duì)象數(shù)據(jù)成員是指針類型時(shí),不是復(fù)制該指針成員本身,而是將指針?biāo)笇?duì)象進(jìn)行復(fù)制。

    2.6 初始化列表

    作用:C++提供了初始化列表語(yǔ)法,用來初始化屬性

    語(yǔ)法:構(gòu)造函數(shù)(): 屬性1(值1), 屬性2(值2) ... {}

    class Person{ public:// 傳統(tǒng)初始化操作Person(int a, int b, int c){m_A = a;m_B = b;m_C = c;}// 初始化列表初始化屬性 Person(int a, int b, int c):m_A(a),m_B(b),m_C(c){}// 注意冒號(hào)“:”的位置,在參數(shù)列表之后。int m_A;int m_B;int m_C; };

    2.7 類對(duì)象作為類成員

    C++類中的成員可以是另一個(gè)類的對(duì)象,我們稱該成員為對(duì)象成員。

    class A{} class B{A a; }

    B類中有對(duì)象A作為成員,A為對(duì)象成員

    // 當(dāng)有其他類對(duì)象作為本類成員,構(gòu)造時(shí)先構(gòu)造類對(duì)象,再構(gòu)造自身; 析構(gòu)順序是先進(jìn)(自身)后出(其他類對(duì)象)

    2.8 靜態(tài)成員

    靜態(tài)成員就是在成員變量和成員函數(shù)前加上關(guān)鍵字static,稱為靜態(tài)成員

    靜態(tài)成員分為:

  • 靜態(tài)成員變量

    • 所有對(duì)象共享同一份數(shù)據(jù)
    • 在編譯階段分配內(nèi)存(提前了)
    • 類內(nèi)聲明,類外初始化
    • 可以通過類名直接訪問靜態(tài)成員變量
    • 私有靜態(tài)成員不能被外部訪問
    // 靜態(tài)成員變量 類內(nèi)聲明, 類外初始化 class Person{ public:static int m_A; // 類內(nèi)聲明 private:static int m_B; // 私有靜態(tài)成員 }; int Person::m_A = 100; // 類外初始化 int Person::m_B = 200; // 可以進(jìn)行類外初始化 Person::m_A; // 使用類名直接訪問 Person::m_B; // 錯(cuò)誤,私有靜態(tài)成員不能訪問。
  • 靜態(tài)成員函數(shù)

    • 所有對(duì)象共享同一個(gè)函數(shù)
    • 靜態(tài)成員函數(shù) 只能 訪問靜態(tài)成員變量
    • 也是有訪問權(quán)限的
    class Person{ public:static void func(){m_A = 100; // 正確。 靜態(tài)成員函數(shù) 可以 訪問靜態(tài)成員變量m_B = 200; // 錯(cuò)誤。 靜態(tài)成員函數(shù) 不可以 訪問非靜態(tài)成員變量// m_A 靜態(tài)成員變量,只有一份數(shù)據(jù), 不具體屬于某一對(duì)象// m_B 屬于特定對(duì)象,無法區(qū)分是哪個(gè)m_Bcout << "static void func調(diào)用" << endl;}static int m_A;int m_B; }; // 通過對(duì)象訪問 Person p; p.func(); // 通過類名訪問 Person::func(); // "::"作用域限定符
  • 3、 C++ 對(duì)象模型和this指針

    3.1 成員變量和成員函數(shù)分開存儲(chǔ)

    在C++中,類內(nèi)的成員變量和成員函數(shù)分開存儲(chǔ)

    只有非靜態(tài)成員變量才存儲(chǔ)在類的對(duì)象上

    // 空對(duì)象 class Person {}; Person p; // 占用內(nèi)存空間 sizeof(p) 為1 // C++ 編譯器會(huì)給每個(gè)空對(duì)象也分配一個(gè)字節(jié)空間,是為了區(qū)分空對(duì)象占內(nèi)存的位置 // 每個(gè)空對(duì)象也應(yīng)該有一個(gè)獨(dú)一無二的內(nèi)存地址 // 非靜態(tài)成員 class Person{ int a; }; Person p; // 占用內(nèi)存空間 sizeof(p) 為4 // 非靜態(tài)成員函數(shù) 存儲(chǔ)不在對(duì)象上 class Person{ void setA(int a) {};int a; }; Person p; // 占用內(nèi)存空間 sizeof(p) 為4 // 靜態(tài)成員 存儲(chǔ)不在對(duì)象上 class Person{ int a; static int b;}; Person p; // 占用內(nèi)存空間 sizeof(p) 為4,

    3.2 this指針

    每一個(gè) 非靜態(tài)成員函數(shù) 只會(huì)誕生一份函數(shù)實(shí)例,也就是說多個(gè)類型的對(duì)象會(huì)共用一塊代碼

    這一塊代碼是如何區(qū)分哪個(gè)對(duì)象調(diào)用自己?

    C++ 提供 this 指針來區(qū)分,this指針指向被調(diào)用的成員函數(shù)所屬的對(duì)象。

    this指針:

  • this指針是隱含在每一個(gè)非靜態(tài)成員函數(shù)內(nèi)的一種指針
  • 不需要定義,直接使用即可
  • 用途:

  • 當(dāng)形參和成員變量同名時(shí),可以用this指針來區(qū)分

  • 在類的非靜態(tài)成員函數(shù)中返回對(duì)象本身,可以用return *this。

  • class Person{ public:Person(int age){// age = age; // 錯(cuò)誤 形參和成員變量名命沖突this->age = age; // 使用this指針,指向 被調(diào)用的成員函數(shù) 的所屬的對(duì)象 }void PersonAddAge(const Person &p){this->age = p.age;}Person & PersonAddAge2(const Person &p){ //注意要返回本體需要用引用,否則相當(dāng)于另創(chuàng)建一個(gè)this->age = p.age;return *this; // 指向本體}Person PersonAddAge3(const Person &p){ //注意要返回本體需要用引用,否則相當(dāng)于另創(chuàng)建一個(gè)this->age = p.age;return *this; // 指向本體} }; Person p1(10); Person p2(10); p2.PersonAddAge(p1); p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1); // 錯(cuò)誤 p2.PersonAddAge2(p1).PersonAddAge2(p1).PersonAddAge2(p1); //正確 p2.age = 40 p2.PersonAddAge3(p1).PersonAddAge3(p1).PersonAddAge3(p1); //運(yùn)行正確,結(jié)果錯(cuò)誤。p2.age = 20。因?yàn)閜2僅第一次發(fā)生了改變,然后后面因?yàn)槭侵祩鬟f所以是新的對(duì)象發(fā)生改變

    3.3 空指針訪問成員函數(shù)

    C++中空指針也是可以調(diào)用成員函數(shù)的,但是也要注意有沒有用到this指針

    如果用到this指針,需要加以判斷保證代碼的健壯性

    // 空指針調(diào)用成員函數(shù) class Person { public:void showClassName() {cout << "Class name is Person!" << endl;}void showAge() {if (this == nullptr) { return; }cout << "Age is : " << m_age << endl; // m_age實(shí)際上是 this->m_age。 因此如果對(duì)象是空指針就需要加以判斷}int m_age = 20; }; // 調(diào)用 int main() {Person *p = nullptr;p->showClassName();p->showAge();return 0; }

    3.4 const修飾成員函數(shù)

    常函數(shù)

  • 成員函數(shù)后加const后被稱為常函數(shù)
  • 常函數(shù)不可以修改任何成員屬性
  • 成員屬性聲明時(shí)附加關(guān)鍵字 mutable (可變的)后,在常函數(shù)中依然可以修改
  • 常對(duì)象

  • 聲明對(duì)象前加const稱該對(duì)象為常對(duì)象
  • 常對(duì)象只能調(diào)用常函數(shù)
  • class Person { public:// this 是一個(gè)指針常量,相當(dāng)于"類名 * const this"(值可以修改,指向不可以修改)// 在成員函數(shù)后面加const,修飾的是this,讓指針指向的值也不可以修改// 等價(jià)于 "const 類名 const this" ;void showPerson() const { // 常函數(shù)this->m_B = 100; // this // this->m_A = 100; // this 相當(dāng)于 Person * const this}int m_A = 20;mutable int m_B = 10; // 特殊字段,在常函數(shù)、常對(duì)象下都可以修改 };void test() {const Person p; //在對(duì)象前加const,變?yōu)槌?duì)象p.m_B = 100; // 常對(duì)象中mutable修飾的屬性可以修改p.showPerson(); // 常對(duì)象只能調(diào)用常函數(shù),因?yàn)槠胀ê瘮?shù)可以修改屬性值 }

    4、 友元

    在程序里,有些私有屬性也想讓類外特殊的一些函數(shù)或者類進(jìn)行訪問,就需要用到友元技術(shù)

    目的:讓一個(gè)函數(shù)或者類,可以訪問另一個(gè)類中的私有成員

    關(guān)鍵字:friend

    友元的三種實(shí)現(xiàn)

    • 全局函數(shù)做友元 , 可以將全局函數(shù)放在類內(nèi)實(shí)現(xiàn)
    • 類做友元
    • 成員函數(shù)做友元
    // 全局函數(shù)做友元 class Building {friend void GoodGay(Building* building); public:Building(){m_SittingRoom = "客廳";m_BedRoom = "臥室";}string m_SittingRoom; private:string m_BedRoom; };// 全局函數(shù) 訪問公有和私有屬性 void GoodGay(Building *building) {cout << "全局函數(shù)好基友正在訪問公有屬性:" << building->m_SittingRoom << endl;cout << "全局函數(shù)好基友正在訪問私有屬性:" << building->m_BedRoom << endl; }int main() {Building b;GoodGay(&b);return 0; }

    類做友元

    語(yǔ)法: friend class 類名;

    類做友元會(huì)用到 前向引用聲明:(多類相互引用的情況,類先聲明后使用)

  • 當(dāng)需要在某個(gè)類的聲明之前,引用該類,則需要進(jìn)行前向引用聲明
  • 前向引用聲明只為程序引入一個(gè)標(biāo)識(shí)符,但具體聲明在其他地方
  • 注意事項(xiàng):

  • 在提供一個(gè)完整的類聲明之前,不能聲明該類的對(duì)象,也不能在內(nèi)聯(lián)成員函數(shù)中使用該類的對(duì)象
  • 當(dāng)使用前向引用聲明時(shí),只能使用被聲明符號(hào),而不能涉及類的任何細(xì)節(jié)
  • // 類做友元 class Building; // 前向引用聲明。 class GoodGay { public:GoodGay();void visit(); // 參觀函數(shù),訪問Building屬性Building* building; };class Building {friend class GoodGay; // 類友元 public:Building();string m_SittingRoom;private:string m_BedRoom; };GoodGay::GoodGay() {this->building = new Building; }void GoodGay::visit() {cout << "GoodGay正在visit:" << building->m_SittingRoom << endl;cout << "GoodGay正在visit:" << building->m_BedRoom << endl; } Building::Building() { //構(gòu)造函數(shù)在類外實(shí)現(xiàn){this->m_SittingRoom = "客廳";this->m_BedRoom = "臥室";} }int main() {GoodGay g;g.visit();return 0; }

    成員函數(shù)做友元

    語(yǔ)法: friend 返回值類型 類名::函數(shù)名();

    #include<iostream> #include<string> using namespace std;class Building; // 前向引用聲明。 class GoodGay { public:GoodGay();void visit(); // 訪問Building屬性中的私有成員void visit2(); // 不能訪問Building屬性中的私有成員Building* building; };class Building {friend void GoodGay::visit(); // 成員函數(shù)作為友元 public:Building();string m_SittingRoom;private:string m_BedRoom; };GoodGay::GoodGay() {building = new Building; }void GoodGay::visit() {cout << "GoodGay正在visit:" << building->m_SittingRoom << endl;cout << "GoodGay正在visit:" << building->m_BedRoom << endl; }void GoodGay::visit2() {cout << "GoodGay正在visit:" << building->m_SittingRoom << endl;// cout << "GoodGay正在visit:" << building->m_BedRoom << endl; 不能訪問 } Building::Building() { //構(gòu)造函數(shù)在類外實(shí)現(xiàn){m_SittingRoom = "客廳";m_BedRoom = "臥室";} }int main() {GoodGay g;g.visit();g.visit2();return 0; }

    5、 運(yùn)算符重載

    概念: 對(duì)已有運(yùn)算符進(jìn)行重新定義,賦予其另一種功能,以適應(yīng) 不同的數(shù)據(jù)類型

    5.1 加號(hào)運(yùn)算符重載

    operater

  • 成員函數(shù)重載
  • 全局函數(shù)重載
  • // 加號(hào)運(yùn)算符重載 class Person{ public:// 成員函數(shù)重載Person operater+(Person &p){Person temp;temp.m_A = this->m_A + p.m_A;temp.m_B = this->m_B + p.m_B;return temp;}int m_A = 10;int m_B = 10; } Person p1; Person p2; Person p3 = p1 + p2; // 本質(zhì)上 p1.operater+(p2)// 全局函數(shù)重載 Person operater+(Person &p1, Person &p2){Person temp;temp.m_A = p1.m_A + p2.m_A;temp.m_B = p1.m_B + p2.m_B;return temp; } Person p3 = p1 + p2; // 本質(zhì)上 operater+(p1, p2)

    運(yùn)算符重載也可以發(fā)生函數(shù)重載

    總結(jié)

  • 對(duì)于內(nèi)置數(shù)據(jù)類型的運(yùn)算符是不能重載的

  • 不要濫用運(yùn)算符重載

  • 5.2 左移運(yùn)算符重載

    作用:重載左移運(yùn)算符 配合友元 可以實(shí)現(xiàn)輸出自定義數(shù)據(jù)類型

    // 左移運(yùn)算符重載 不能通過成員函數(shù)實(shí)現(xiàn),只能利用全局函數(shù)重載左移運(yùn)算符 // 訪問私有類時(shí),可以將全局函數(shù)聲明為友元函數(shù)。 class Person {friend ostream& operator<<(ostream& cout, Person& p); public:// 利用成員函數(shù)重載 左移運(yùn)算符// 不會(huì)利用成員函數(shù)重載左移<<運(yùn)算符,因?yàn)闊o法實(shí)現(xiàn)cout為左值Person(int a, int b) {this->m_A = a;this->m_B = b;} private:int m_A;int m_B; };// 只能利用全局函數(shù)重載左移運(yùn)算符 // 不能用void 用 ostream類 ostream & operator<<(ostream& cout, Person p) {cout << "m_A = " << p.m_A << " m_B = " << p.m_B;return cout; } int main() {Person p(10,10);return 0; }

    5.3 遞增運(yùn)算符重載

    作用:通過重載遞增運(yùn)算符,來自己實(shí)現(xiàn)的整型數(shù)據(jù)類型

    class MyInteger { public:MyInteger(){m_Num = 0;}// 重載前置運(yùn)算符遞增 返回引用是為了一直只對(duì)一個(gè)對(duì)象修改MyInteger& operator++(){m_Num++;return *this;}// 重載后置運(yùn)算符遞增// void operator++(int) int表示占位參數(shù),可以用于區(qū)分前置和后置遞增// 注意:這里只能用 intMyInteger operator++(int) { // 先記錄當(dāng)前結(jié)果MyInteger temp = *this; // 局部非靜態(tài)變量 因此返回值不是引用。// 后遞增m_Num++;// 最后將記錄結(jié)果返回return temp; // }int m_Num = 0; };// 為什么使用后置遞增運(yùn)算 用引用傳參&myint會(huì)報(bào)錯(cuò) ostream& operator<<(ostream& out, MyInteger myint) {out << myint.m_Num << endl;return out; }int main() {MyInteger myint;cout << ++myint << endl;cout << myint << endl;MyInteger myint2 = myint++;cout << myint2 << endl;cout << &(myint++) << endl;return 0; }

    為什么使用后置遞增運(yùn)算 用引用傳參 MyInteger &myint會(huì)報(bào)錯(cuò)?

    因?yàn)楹笾眠f增返回臨時(shí)對(duì)象,不能綁定到非常量引用。所以那個(gè)形參必須寫成const引用。打印函數(shù)不會(huì)更改對(duì)象,所以最好要寫成const形式。通常來說const形參適用面廣一些(常量,非常量都能傳進(jìn)去)。第二,推薦ostream& operator<<形參別寫成cout,造成誤導(dǎo)。

    加入const之后,編譯器將代碼修改為:

    MyInteger temp = 后置遞增的值; const MyInteger & myint = temp;

    只有傳入的是臨時(shí)對(duì)象時(shí),才發(fā)生復(fù)制構(gòu)造。

    5.4 賦值運(yùn)算符重載

    C++ 編譯器至少給一個(gè)類添加4個(gè)函數(shù):

  • 默認(rèn)構(gòu)造函數(shù)(無參,函數(shù)體為空)
  • 默認(rèn)析構(gòu)函數(shù)(無參,函數(shù)體為空)
  • 默認(rèn)拷貝構(gòu)造函數(shù),對(duì)屬性進(jìn)行值拷貝
  • 賦值運(yùn)算符operator=, 對(duì)屬性進(jìn)行值拷貝
  • 如果類中有屬性指向堆區(qū),做賦值操作時(shí)也會(huì)出現(xiàn)深淺拷貝問題。

    // 賦值運(yùn)算符重載 #include<iostream> #include<string> using namespace std;class Person { public:Person(int age) {m_Age = new int(age);}~Person() {if (m_Age != nullptr) {delete m_Age;m_Age = nullptr;}}Person &operator=(Person& p) {// 編譯器是提供淺拷貝// m_Age = p.m_Age;// 應(yīng)該先判斷是否有屬性在堆區(qū),如果有先釋放干凈,然后再深拷貝if (m_Age != nullptr) {delete m_Age;m_Age = nullptr;}// 深拷貝m_Age = new int(*p.m_Age);//返回對(duì)象自身return *this;}int* m_Age; }; int main() {Person p1(18);cout << "p1的年齡是:" << *p1.m_Age << endl;Person p2(20);cout << "p2的年齡是:" << *p2.m_Age << endl;p2 = p1;cout << "p2的年齡是:" << *p2.m_Age << endl;Person p3(60);p3 = p2 = p1;cout << "p3的年齡是:" << *p3.m_Age << endl;return 0; }

    總結(jié): 鏈?zhǔn)骄幊桃⒁夥祷刂档念愋?#xff0c;如重載遞增運(yùn)算、賦值運(yùn)算都需要注意。

    5.5 關(guān)系運(yùn)算符重載

    作用:重載關(guān)系運(yùn)算符,可以讓兩個(gè)自定義類型對(duì)象進(jìn)行對(duì)比操作

    // 舉例 重載== bool operator==(Person &p){if(this->m_A == p.m_A && this->m_Age == p.m_Age){return true;}return false; }

    5.6 函數(shù)調(diào)用運(yùn)算符重載()

    • 函數(shù)調(diào)用運(yùn)算符 () 也可以重載
    • 由于重載后使用的方式非常像函數(shù)的調(diào)用,因此稱為仿函數(shù)
    • 仿函數(shù)沒有固定寫法, 非常靈活
    class MyPrint { public:// 重載函數(shù)調(diào)用運(yùn)算符void operator()(string text) {cout << text << endl;}void operator()(string text, string text2) {cout << text+text2 << endl;} }; int main() {MyPrint myprint;myprint("hello world"); // 仿函數(shù)// 匿名函數(shù)對(duì)象MyPrint()("匿名函數(shù)對(duì)象");return 0; }

    6、繼承

    繼承是面向?qū)ο笕筇匦灾?/strong>。可以減少重復(fù)代碼

    6.1 繼承的基本語(yǔ)法

    語(yǔ)法:class 子類 : 繼承方式 父類

    術(shù)語(yǔ): 子類又稱 派生類,父類又稱 基類

    派生類中的成員包含兩大部分

    一類是從基類中繼承來的,另一類是它自身的成員

    6.2 繼承方式

    繼承有三種方式

    父類中的私有private內(nèi)容,子類無論哪種方式都不能訪問。

    • 公共繼承 :父類中public、protected在子類的訪問權(quán)限不變
    • 保護(hù)繼承 :父類中public、protected在子類中訪問權(quán)限變?yōu)閜rotected
    • 私有繼承 :父類中public、protected在子類中訪問權(quán)限變?yōu)閜rivate

    6.3 繼承中的對(duì)象模型

    問題:從父類繼承過來的成員, 哪些屬于子類對(duì)象中?

  • 私有成員只是被隱藏了,但是還是會(huì)繼承下去 。
  • class Base{ public:int m_A; protected:int m_B; private:int m_C; // 私有成員只是被隱藏了,但是還是會(huì)繼承下去 }; // class Son :public Base { public:int m_D; };int main() {Son s1;cout << sizeof(s1) << endl; // 輸出 16return 0; } 利用開發(fā)人員命令提示工具查看對(duì)象模型 cl /d1 reportSingleClassLayout類名 "文件名"

    6.4 繼承中的構(gòu)造和析構(gòu)

    子類繼承父類后,當(dāng)創(chuàng)建子類對(duì)象,也會(huì)調(diào)用父類的構(gòu)造函數(shù)

    問題: 父類和子類的構(gòu)造和析構(gòu)順序誰(shuí)先誰(shuí)后?

    先父類構(gòu)造,后子類構(gòu)造;先析構(gòu)子類,后析構(gòu)父類,與構(gòu)造相反

    // 繼承中的構(gòu)造和析構(gòu)順序 class Base { public:Base() {cout << "Base的構(gòu)造函數(shù)!" << endl;}~Base() {cout << "Base的析構(gòu)函數(shù)!" << endl;} };class Son :public Base { public:Son() {cout << "Son的構(gòu)造函數(shù)!" << endl;}~Son() {cout << "Son的析構(gòu)函數(shù)!" << endl;} };int main() {Son s1;return 0; }

    6.5 繼承中同名成員處理方式

    問題:當(dāng)子類與父類出現(xiàn)同名的成員,如何通過子類對(duì)象,訪問到子類或父類中同名的數(shù)據(jù)呢?

    • 訪問子類同名成員 直接訪問即可
    • 訪問父類同名成員 需要加作用域
    // 繼承中同名成員處理 class Base { public:Base() {m_A = 100;}void func() {cout << "Base - func 函數(shù)" << endl;}void func(int a) {cout << "Base - func(int a) 函數(shù)" << endl;}int m_A; };class Son :public Base { public:Son() {m_A = 200;}void func() {cout << "Son - func 函數(shù)" << endl;}int m_A; };int main() {Son s;// 同名成員屬性cout << "Son 下 m_A = " << s.m_A << endl;cout << "Base 下 m_A = " << s.Base::m_A << endl;// 同名成員函數(shù)s.func();s.Base::func();// 重載// 如果子類中出現(xiàn)和父類同名的成員函數(shù),子類的同名成員會(huì)// 隱藏掉父類中所有同名成員函數(shù)(包含重載函數(shù))// 如果想要訪問父類中被隱藏的同名成員函數(shù),需要加作用域s.Base::func(10);return 0; }

    注意事項(xiàng):

    如果子類中出現(xiàn)和父類同名的成員函數(shù),子類的同名成員會(huì)隱藏掉父類中所有同名成員函數(shù)(包含重載函數(shù))。 如果想要訪問父類中被隱藏的同名成員函數(shù),需要加 作用域

    6.6 繼承中同名靜態(tài)成員處理方式

    問題:繼承中同名的靜態(tài)成員在子類對(duì)象上如何進(jìn)行訪問?

    靜態(tài)成員和非靜態(tài)成員出現(xiàn)同名,處理方式一致

    • 訪問子類同名成員 直接訪問即可
    • 訪問父類同名成員 需要加作用域

    注意:靜態(tài)成員在類內(nèi)聲明,類外初始化。

    // 同名靜態(tài)成員 與 同名靜態(tài)成員函數(shù) class Base { public:static int m_A;static void func() {cout <<" Base - static void func()" << endl;} }; int Base::m_A = 100;class Son :public Base { public:static int m_A;static void func() {cout << " Son - static void func()" << endl;} }; int Son::m_A = 200;int main() {Son s;// 1、通過對(duì)象訪問cout << "Son 下 m_A = " << s.m_A << endl;cout << "Base 下 m_A = " << s.Base::m_A << endl;// 2、通過類名訪問cout << "Son 下 m_A = " << Son::m_A << endl;cout << "Base 下 m_A = " << Son::Base::m_A << endl;// Son::Base::m_A 通過類名方式訪問Son中Base作用域下的m_A// 1、通過對(duì)象訪問s.func();s.Base::func();// 2、通過類名訪問Son::func();Son::Base::func();return 0; }

    6.7 多繼承語(yǔ)法

    C++允許一個(gè)類繼承多個(gè)語(yǔ)法

    語(yǔ)法: class 子類: 繼承方式 父類1, 繼承方式 父類2 ...

    多繼承可能會(huì)引發(fā)父類中有同名成員出現(xiàn),需要加作用域區(qū)分。

    實(shí)際開發(fā)中不建議用多繼承

    // 多繼承 class A { public:A() {cout << "Create A !" << endl;}int m_N; };class B { public:B() {cout << "Create B !" << endl;}int m_N; };class C : public A, public B{ // 多繼承語(yǔ)法 public:C() {m_C = 100;m_D = 200;cout << "Create C !" << endl;}int m_C;int m_D; }; int main() {C c;cout << "This is A:" << c.A::m_N << endl;cout << "This is B:" << c.B::m_N << endl;return 0; }

    6.8 菱形繼承

    菱形繼承的概念

    ? 兩個(gè)派生類繼承同一個(gè)基類, 又有某個(gè)類同時(shí)繼承兩個(gè)派生類。這種繼承被稱為菱形繼承,或者鉆石繼承。

    問題:

    • 二義性

    • 有的數(shù)據(jù)重復(fù),只需要一項(xiàng)就可以

    class Animal { // 虛基類 public:int m_age; }; // 利用虛繼承解決菱形繼承的問題 // 繼承之前加上關(guān)鍵字 virtual 變?yōu)樘摾^承 // Animal 類稱為虛基類 class Sheep: virtual public Animal{}; class Tuo : virtual public Animal{};class SheepTuo : public Sheep, public Tuo {}; int main() {SheepTuo st;st.Sheep::m_age = 18;st.Tuo::m_age = 28; // 虛繼承 m_age只有一個(gè)// 當(dāng)菱形繼承, 兩個(gè)父類擁有相同數(shù)據(jù),需要加以作用域區(qū)分cout << "st.Sheep :: m_Age = " << st.Sheep::m_age << endl;cout << "st.Sheep :: m_Age = " << st.Tuo::m_age << endl;// 這份數(shù)據(jù)本身只需要有一份就好,菱形繼承導(dǎo)致數(shù)據(jù)有兩份,資源浪費(fèi)cout << "st的m_Age = " << st.m_age << endl;return 0; }

    總結(jié):利用 虛繼承 解決菱形繼承問題。術(shù)語(yǔ)理解:虛基類,虛繼承 關(guān)鍵字 virtual。

    7、多態(tài)

    多態(tài)是 C++ 面向?qū)ο蟮娜筇匦?#xff08;封裝、繼承、多態(tài))之一。

    7.1 多態(tài)的基本概念

    多態(tài)分為兩類:

    • 靜態(tài)多態(tài): 函數(shù)重載和運(yùn)算符重載屬于靜態(tài)多態(tài),復(fù)用函數(shù)名
    • 動(dòng)態(tài)多態(tài)派生類和虛函數(shù)實(shí)現(xiàn)運(yùn)行時(shí)多態(tài)

    靜態(tài)多態(tài)和動(dòng)態(tài)多態(tài)的區(qū)別

    • 靜態(tài)多態(tài)的函數(shù)地址綁定 – 編譯階段確定函數(shù)地址
    • 動(dòng)態(tài)多態(tài)的函數(shù)地址綁定 – 運(yùn)行階段確定函數(shù)地址
    // 動(dòng)物類 class Animal { public: // 虛函數(shù)virtual void speak() {cout << "動(dòng)物在說話" << endl;} };class Cat: public Animal { public: // 重寫 函數(shù)返回值類型 函數(shù)名 參數(shù)列表 完全相同// 此時(shí) virtual 關(guān)鍵字 可寫可不寫, 建議書寫增加可讀性virtual void speak(){cout << "喵喵喵" << endl;} };class Dog : public Animal { public:virtual void speak() {cout << "汪汪汪" << endl;} };// 執(zhí)行說話的函數(shù) // 地址早綁定, 在編譯階段確定函數(shù)地址 // 如果想執(zhí)行讓貓說話,那么這個(gè)函數(shù)地址就不能提前綁定, // 需要在運(yùn)行階段進(jìn)行綁定,地址晚綁定 void doSpeak(Animal &animal) { // C++中可以允許父子之間的數(shù)據(jù)類型轉(zhuǎn)換animal.speak(); }int main() {Cat cat;Dog dog;doSpeak(cat);doSpeak(dog); }

    總結(jié)

    多態(tài)滿足條件:

    • 有繼承關(guān)系
    • 子類重寫父類中的虛函數(shù)

    多態(tài)使用條件

    • 父類的 指針或引用 指向 子類對(duì)象

    重寫: 函數(shù)返回值類型 函數(shù)名 函數(shù)列表 完全一致稱為 重寫

    7.2 虛函數(shù)(考點(diǎn))

    實(shí)現(xiàn)動(dòng)態(tài)綁定的函數(shù)。

    virtual 只是編譯器不要在編譯階段進(jìn)行靜態(tài)綁定。

    虛函數(shù)定義:

  • 用virtual 關(guān)鍵字說明的函數(shù)
  • 虛函數(shù)是實(shí)現(xiàn)運(yùn)行時(shí)多態(tài)的基礎(chǔ)
  • C++虛函數(shù)是動(dòng)態(tài)綁定的函數(shù)
  • 虛函數(shù)必須是 非靜態(tài) 的成員函數(shù),虛函數(shù)經(jīng)過派生后,就可以實(shí)現(xiàn)運(yùn)行過程中的多態(tài)。
  • 什么函數(shù)可以是虛函數(shù)

    • 一般成員函數(shù)

    • 構(gòu)造函數(shù)不能是

    • 析構(gòu)函數(shù)可以是

    一般虛函數(shù)成員

  • 虛函數(shù)聲明 virtual 函數(shù)類型 函數(shù)名(形參表);
  • 函數(shù)聲明只能出現(xiàn)在類定義中的函數(shù)原型聲明中,而不能在成員函數(shù)實(shí)現(xiàn)的時(shí)候。
  • 在派生類中可以對(duì)基類中國(guó)的成員函數(shù)進(jìn)行重寫(覆蓋)。
  • 虛函數(shù)一般不聲明為內(nèi)聯(lián)函數(shù), 因?yàn)閷?duì)虛函數(shù)的調(diào)用需要?jiǎng)討B(tài)綁定,而對(duì)內(nèi)聯(lián)函數(shù)的處理是靜態(tài)的
  • virtual關(guān)鍵字:

    派生類可以不顯式地用 virtual 關(guān)鍵字聲明虛函數(shù),這時(shí)候系統(tǒng)會(huì)根據(jù)以下規(guī)則來判斷派生類地一個(gè)函數(shù)成員是不是虛函數(shù):

  • 該函數(shù)是否與基類的虛函數(shù)有相同的名稱、參數(shù)個(gè)數(shù)及對(duì)應(yīng)參數(shù)類型
  • 該函數(shù)是否與基類的虛函數(shù)有相同的返回值或者滿足類型兼容規(guī)則的指針、引用型的返回值。
  • 如果從名稱、參數(shù)及返回值三個(gè)方面檢查之后,派生類的函數(shù)滿足上述條件,就會(huì)自動(dòng)確定為虛函數(shù)。這時(shí),派生類的虛函數(shù)便覆蓋了基類的虛函數(shù)。
  • 派生類中的虛函數(shù)還會(huì)隱藏基類中同名函數(shù)的所有其他重載形式
  • 一般習(xí)慣于在派生類中函數(shù)中也使用 virtual 關(guān)鍵字, 以增加程序的可讀性。
  • 7.3 多態(tài)的基本概念

    虛函數(shù)指針 vfptr

    虛函數(shù)表 vftable:

    • 每一個(gè)多態(tài)類都有一個(gè)虛表

    • 虛表中有當(dāng)前類的各個(gè)虛函數(shù)的入口地址

    • 每個(gè)對(duì)象隱含有一個(gè)指向當(dāng)前類的虛表的指針

    7.4 多態(tài)案例

    多態(tài)案例一:計(jì)算器類

    案例描述: 分別利用普通寫法和多態(tài)技術(shù),設(shè)計(jì)實(shí)現(xiàn)兩個(gè)操作數(shù)進(jìn)行運(yùn)算的計(jì)算器類

    多態(tài)的優(yōu)點(diǎn):

    • 代碼組織結(jié)構(gòu)清晰
    • 可讀性強(qiáng)
    • 利于前期和后期的擴(kuò)展以及維護(hù)
    // 普通寫法 class Calculator{ public:int getResult(string oper) {if (oper == "+") {return m_Num1 + m_Num2;}else if (oper == "-") {return m_Num1 - m_Num2;}else if (oper == "*") {return m_Num1 * m_Num2;}}int m_Num1;int m_Num2; };int main() {Calculator c;c.m_Num1 = 10;c.m_Num2 = 10;cout << c.m_Num1 << " + " << c.m_Num2 << " = " << c.getResult("+") << endl; } // 多態(tài)技術(shù) // 實(shí)現(xiàn)計(jì)算器抽象類 class AbstractCalclator { public:virtual int getResult(){return 0;}int m_Num1;int m_Num2; };class AddCalculator : public AbstractCalclator { public:virtual int getResult(){return m_Num1 + m_Num2;} };class SubCalculator : public AbstractCalclator { public:virtual int getResult() {return m_Num1 - m_Num2;} };class MulCalculator : public AbstractCalclator { public:virtual int getResult() {return m_Num1 * m_Num2;} }; int main() {// 多態(tài)的使用條件 // 父類的 "指針或者引用" 指向 子類對(duì)象AbstractCalclator* abc = new AddCalculator;abc->m_Num1 = 10;abc->m_Num2 = 10;cout << abc->m_Num1 << " + " << abc->m_Num2 << " = " << abc->getResult() << endl;// new 分配的堆內(nèi)存 用完記得銷毀delete abc;abc = new SubCalculator;abc->m_Num1 = 10;abc->m_Num2 = 10;cout << abc->m_Num1 << " + " << abc->m_Num2 << " = " << abc->getResult() << endl;// new 分配的堆內(nèi)存 用完記得銷毀delete abc; }

    7.5 純虛函數(shù)和抽象類

    在多態(tài)中,通常父類中虛函數(shù)的實(shí)現(xiàn)是毫無意義的,主要都是調(diào)用子類重寫的內(nèi)容

    因此 可以將虛函數(shù)改為純虛函數(shù)

    純虛函數(shù)語(yǔ)法: virtual 返回值類型 函數(shù)名 (參數(shù)列表) = 0;

    當(dāng)類中有了純虛函數(shù),這個(gè)類也稱為抽象類。

    抽象類的特點(diǎn):

    • 無法實(shí)例化對(duì)象
    • 子類必須重寫抽象類中的純虛函數(shù),否則也屬于抽象類
    class AbstractCalclator { // 抽象類 public:virtual int getResult() = 0; // 純虛函數(shù)int m_Num1;int m_Num2; };

    7.6 虛析構(gòu)和純虛析構(gòu)

    多態(tài)使用時(shí), 如果子類中有屬性開辟到堆區(qū), 那么父類指針在釋放時(shí)無法調(diào)用到子類的析構(gòu)代碼。

    解決方式:將父類中的析構(gòu)函數(shù)改為虛析構(gòu)或者純虛析構(gòu)

    虛析構(gòu)和純虛析構(gòu)共性

    • 可以解決父類指針釋放子類對(duì)象
    • 都需要具體函數(shù)實(shí)現(xiàn)

    區(qū)別

    • 如果是純虛析構(gòu),該類屬于抽象類,無法實(shí)例化對(duì)象。

    語(yǔ)法

    虛析構(gòu)語(yǔ)法:virtual ~類名(){}

    純虛析構(gòu)語(yǔ)法: virtual ~類名 = 0; 類名::~類名(){} 純虛析構(gòu) 需要有聲明 類外寫實(shí)現(xiàn)

    class Animal { public:Animal() {cout << "Animal類的構(gòu)造函數(shù)調(diào)用" << endl;}// 利用虛析構(gòu)可以解決 父類指針釋放子類對(duì)象時(shí)不干凈的問題/*virtual ~Animal() {cout << "Animal類的析構(gòu)函數(shù)調(diào)用" << endl;}*/// 純虛析構(gòu) 需要有聲明 也需要有實(shí)現(xiàn)的// 有了純虛析構(gòu)之后, 這個(gè)類也屬于抽象類virtual ~Animal() = 0;// 純虛函數(shù)virtual void speak() = 0; }; // 純虛析構(gòu)后 在外部實(shí)現(xiàn)析構(gòu)函數(shù) Animal::~Animal() {cout << "Animal類的析構(gòu)函數(shù)調(diào)用" << endl;}class Cat: public Animal { public:Cat(string name) {cout << "Cat類構(gòu)造函數(shù)調(diào)用" << endl;this->m_Name = new string(name);}~Cat(){if (this->m_Name != nullptr) {cout << "Cat類析構(gòu)函數(shù)調(diào)用" << endl;delete this->m_Name;m_Name = nullptr;}}virtual void speak() {cout << *this->m_Name <<"小貓?jiān)谡f話" << endl;}string* m_Name; };int main() {Animal* animal = new Cat("Tom");animal->speak();// 父類指針在析構(gòu)時(shí)候 不會(huì)調(diào)用子類中的析構(gòu)函數(shù),導(dǎo)致子類如果有堆區(qū)屬性,// 會(huì)出現(xiàn)內(nèi)存泄露情況delete animal;return 0; }

    總結(jié)

  • 虛析構(gòu)和純虛析構(gòu)就是用來解決通過父類指針釋放子類對(duì)象的問題
  • 如果子類中沒有堆數(shù)據(jù),可以不寫為虛析構(gòu)和純虛析構(gòu)
  • 擁有純虛析構(gòu)函數(shù)的類也屬于抽象類
  • 7.7 override 和 final

    override:C++ 11中引入的顯示覆蓋。使用override后,編譯器會(huì)檢查基類中是否存在一虛函數(shù),與派生類中帶有聲明override的虛函數(shù),有相同的虛函數(shù)簽名(函數(shù)名 參數(shù)列表 const一致),若不存在,則返回錯(cuò)誤

    final:不希望類或函數(shù)被修改,使用final聲明則該類(或函數(shù))將不能被繼承(或覆蓋)。

    class Base final{}; virtual void f() final;

    8、文件操作

    程序運(yùn)行時(shí)產(chǎn)生的數(shù)據(jù)都屬于臨時(shí)數(shù)據(jù),程序一旦運(yùn)行結(jié)束都會(huì)被釋放, 通過文件可以將 數(shù)據(jù)持久化

    C++中對(duì)文件操作需要包含頭文件 #include<fstream>

    文件類型分為兩種:

  • 文本文件 - 文件以文本的ASCII碼形式存儲(chǔ)在計(jì)算機(jī)中
  • 二進(jìn)制文件 - 文件以文本的二進(jìn)制形式存儲(chǔ)在計(jì)算機(jī)中,用戶一般不能直接讀懂它們
  • 操作文件的三大類:

  • ofstream : 寫操作
  • ifstream : 讀操作
  • fstream: 讀寫操作
  • 8.1 文本文件

    寫文件的步驟

  • 包含頭文件 #include <fstream>
  • 創(chuàng)建流對(duì)象 ofstream ofs;
  • 打開文件 ofs.open("文件路徑", 打開方式);
  • 寫數(shù)據(jù) ofs << "寫入數(shù)據(jù)";
  • 關(guān)閉文件 ofs.close();
  • 文件打開方式

    打開方式解釋
    ios::in為讀文件而打開文件
    ios::out為寫文件而打開文件
    ios::ate初始位置:文件尾
    ios::app追加方式寫文件
    ios::trunc如果文件存在先刪除,再創(chuàng)建
    ios::binary二進(jìn)制方式

    注意:文件打開方式可以配合使用, 利用|操作符

    例如:用二進(jìn)制方式寫文件ios::binary | ios::out

    #include<fstream> int main() {// 2、創(chuàng)建流對(duì)象ofstream ofs;// 3、制定打開方式ofs.open("test.txt", ios::out);// 4、寫內(nèi)容ofs << "姓名:張三" << endl;ofs << "性別:男" << endl;ofs << "年齡:18" << endl;ofs.close();return 0; }

    讀文件的步驟

  • 包含頭文件 #include <fstream>
  • 創(chuàng)建流對(duì)象 ifstream ifs;
  • 打開文件并判斷文件是否打開成功: ifs.open("文件路徑", 打開方式);
  • 寫數(shù)據(jù) 四種方式讀取
  • 關(guān)閉文件 ifs.close();
  • int main() {// 2、創(chuàng)建流對(duì)象ifstream ifs;// 3、打開文件 并且判斷是否打開成功ifs.open("test.txt", ios::out);if (!ifs.is_open()) {cout << "文件打開失敗" << endl;return 0; }// 4、讀內(nèi)容// 第一種char buf[1024] = { 0 };while (ifs >> buf) {cout << buf << endl;}// 第二種char buf[1024] = { 0 };while (ifs.getline(buf, sizeof(buf))) {cout << buf << endl;}// 第三種string buf;while (getline(ifs, buf)) {cout << buf << endl;}// 第四種char c;while ((c = ifs.get()) != EOF) // End of File{cout << buf << endl;}// 5、關(guān)閉ifs.close();return 0; }

    8.2 二進(jìn)制文件

    以二進(jìn)制的方式對(duì)文件進(jìn)行讀寫操作,打開方式要指定為 ios::binary 。

    寫文件

    二進(jìn)制方式寫文件主要利用流對(duì)象調(diào)用成員函數(shù) write

    函數(shù)原型:ostream& write(const char * buffer, int len);

    參數(shù)解釋:字符指針buffer指向內(nèi)存中一段存儲(chǔ)空間。len是讀寫的字節(jié)數(shù)。

    // 二進(jìn)制文件 寫文件 注意二進(jìn)制寫文件盡量不要用string class Person { public:char m_Name[64]; // 姓名int m_Age; // 年齡 };int main() {// 2、 創(chuàng)建流對(duì)象ofstream ofs("person.txt", ios::out | ios::binary); //創(chuàng)建流對(duì)象時(shí)候直接指定// 3、 打開文件// ofs.open("person.txt", ios::out| ios::binary)// 4、 寫入文件Person p = { "張三", 18 };ofs.write((const char *)&p,sizeof(Person));// 5、 關(guān)閉文件ofs.close();return 0; }

    總結(jié)://創(chuàng)建流對(duì)象時(shí)候直接指定

    讀文件

    二進(jìn)制讀文件主要利用流對(duì)象調(diào)用成員函數(shù)read

    函數(shù)原型:istream& read(char * buffer, int len);

    參數(shù)解釋: buffer指向內(nèi)存中一段存儲(chǔ)空間,len是讀寫的字節(jié)數(shù)。

    // 二進(jìn)制文件 讀文件 class Person { public:char m_Name[64]; // 姓名int m_Age; // 年齡 };int main() {// 2、 創(chuàng)建流對(duì)象ifstream ifs("person.txt", ios::out | ios::binary); //創(chuàng)建流對(duì)象時(shí)候直接指定// 3、 打開文件 判斷文件是否打開成功if (!ifs.is_open()) {cout << "打開成功" << endl;}// 4、 寫入文件Person p;ifs.read((char *)&p,sizeof(Person));cout << "姓名: " << p.m_Name << " 年齡:" << p.m_Age << endl;// 5、 關(guān)閉文件ifs.close();return 0; }

    C++泛型編程和STL庫(kù)

    1、模板

    1.1 模板的概念

    模板就是建立通用的模具,大大提高復(fù)用性,例如ppt模板

    缺點(diǎn)

    • 模板不能直接使用
    • 模板并不是萬(wàn)能的,不能包括所有的

    1.2 函數(shù)模板

    泛型編程

    • C++另一種編程思想稱為泛型編程, 主要利用的技術(shù)就是模板
    • C++提供兩種模板機(jī)制: 函數(shù)模板類模板

    函數(shù)模板的語(yǔ)法

    函數(shù)模板的作用:建立一個(gè)通用參數(shù),其函數(shù)返回值類型和形參類型可以不具體指定,用一個(gè)虛擬的類型來代表。

    語(yǔ)法

    template<typename T> 函數(shù)聲明或定義

    解釋

    template — 聲明創(chuàng)建模板

    typename — 表明其后面的符號(hào)是一種數(shù)據(jù)類型,可以用class代替

    T — 通用的數(shù)據(jù)類型,名稱可以替換,通常為大寫字母

    // 什么情況下用函數(shù)模板 // 下面是兩個(gè)普通函數(shù),針對(duì)每一個(gè)數(shù)據(jù)類型都要單獨(dú)實(shí)現(xiàn)函數(shù) void swapInt(int &a, int &b) {int temp = a;a = b;b = temp; } void swapDouble(double& a, double& b) {double temp = a;a = b;b = temp; }// 聲明一個(gè)模板,告訴編譯器后面代碼緊跟著T不要報(bào)錯(cuò),T是一個(gè)通用數(shù)據(jù)類型 template <typename T> // typename class都可以 void mySwap(T& a, T& b) {T temp = a;a = b;b = temp; }int main() {int a = 10;int b = 20;// 使用函數(shù)模板// 1、自動(dòng)類型推導(dǎo)mySwap(a, b);cout << "a is " << a << " b is " << b << endl;// 2、顯示指定類型mySwap<int>(a, b);return 0; }

    總結(jié):

    • 函數(shù)模板利用關(guān)鍵字 template
    • 使用函數(shù)模板有兩種方式: 自動(dòng)類型推導(dǎo)、顯示指定類型
    • 模板的目的是為了提高復(fù)用性,將類型參數(shù)化

    1.3 函數(shù)模板注意事項(xiàng)

    • 自動(dòng)類型推導(dǎo),必須推導(dǎo)出一致的數(shù)據(jù)類型T,才可以使用
    • 模板必須要確定出T的類型,才可以使用
    // 第一種情況 templete <class T>; void mySwap(T &a,T &b) {} int a = 10; double = 1.5; mySwap(a, b); // 錯(cuò)誤。 無法從int double中推導(dǎo)出類型T // 第二種錯(cuò)誤情況 templete <class T>; void func(){函數(shù)體; } func(); // 錯(cuò)誤,不能確定出T的類型 func<T>(); // 確定T的類型

    1.4 函數(shù)模板案例

    案例描述:

    • 利用函數(shù)模板封裝一個(gè)排序的函數(shù),可以對(duì)不同數(shù)據(jù)類型數(shù)組進(jìn)行排序
    • 排序規(guī)則從大到小,排序算法為選擇排序
    • 分別利用char 數(shù)組和int數(shù)組進(jìn)行測(cè)試
    // 交換函數(shù) template <class T> void mySwap(T& a, T& b) {T temp = a;a = b;b = temp; }template <class T> void mySort(T *arr, int len) {for (int i = 0; i < len; i++) {int max = i;for (int j = i + 1; j < len; j++) {if (arr[j] > arr[max]) { // 找出最大值max = j;}}if (max != i) {mySwap(arr[i], arr[max]);}} } // 打印模板 template<class T> void printArr(T* arr, int len) {for (int i = 0; i < len; i++) {cout << arr[i] << "\t";}cout << endl; }int main() {char cArr[] = "badcfe";int clen = sizeof(cArr) / sizeof(char);mySort<char>(cArr,clen);printArr<char>(cArr,clen);int arr[] = {2,4,5,65,65,32,1,5};int alen = sizeof(arr) / sizeof(int);mySort<int>(arr, alen);printArr<int>(arr, alen);return 0; }

    總結(jié):

    函數(shù)模板如何聲明,如何在不同文件中使用?

    1.5 普通函數(shù)與函數(shù)模板的區(qū)別

    普通函數(shù)與函數(shù)模板的區(qū)別

    • 普通函數(shù)可以發(fā)生自動(dòng)類型轉(zhuǎn)換(隱式類型轉(zhuǎn)換)
    • 函數(shù)模板調(diào)用時(shí),如果利用自動(dòng)類型推導(dǎo),不會(huì)發(fā)生隱式類型轉(zhuǎn)換
    • 如果利用顯式指定類型的方式,可以發(fā)生隱式類型轉(zhuǎn)換
    template <class T> T add(T a, T b) {return a + b; } int a = 10; char b = 'c'; add<int>(a, b); // 正確 // 如果利用顯式指定類型的方式,可以發(fā)生隱式類型轉(zhuǎn)換。 // 為什么 swap<int>(a,b) 不正確, 因?yàn)閭鲄⒎绞绞莻饕梅绞?#xff0c;而不能將一個(gè)char類型的變量綁定到一個(gè)int類型的引用上。

    建議:使用顯式指定類型的方式調(diào)用函數(shù)模板,因?yàn)榭梢宰约捍_定通用類型T。

    1.6 普通函數(shù)與函數(shù)模板的調(diào)用規(guī)則

    調(diào)用規(guī)則

    • 如果函數(shù)模板和普通函數(shù)都可以實(shí)現(xiàn),優(yōu)先調(diào)用普通函數(shù)
    • 可以通過 空模板參數(shù)列表, 強(qiáng)制調(diào)用函數(shù)模板
    • 函數(shù)模板也可以重載
    • 如果函數(shù)模板可以產(chǎn)生更好的匹配,優(yōu)先調(diào)用函數(shù)模板。
    void myPrint(int a, int b) {cout << "普通函數(shù)" << endl; // 刪除函數(shù)體,改成函數(shù)聲明會(huì)報(bào)錯(cuò) }template <class T> void myPrint(T a, T b) {cout << "調(diào)用的模板" << endl; } template <class T> void myPrint(T a, T b, T c) {cout << "調(diào)用重載的模板" << endl; } int main() {int a = 10;int b = 20;// myPrint(a, b); // 普通函數(shù)myPrint<>(a, b); // 空模板參數(shù)列表 強(qiáng)制調(diào)用 函數(shù)模板int c = 30;myPrint<>(a, b, c); //調(diào)用void myPrint(T a, T b, T c)char d = 'd';char e = 'e';myPrint(d, e); // 更好的匹配 所以調(diào)用void myPrint(T a, T b) 普通函數(shù)需要強(qiáng)制類型轉(zhuǎn)換return 0; }

    總結(jié):既然提供了函數(shù)模板,最好就不要再提供普通函數(shù),否則容易出現(xiàn)二義性

    1.7 模板的局限性

    • 模板的通用性并不是萬(wàn)能的
    template <class T> void assignment(T& a, T& b){a = b; } // 如果a、b 傳入的是數(shù)組就無法實(shí)現(xiàn)

    解決方案:C++提供了模板的重載,可以為特定類型提供具體化的模板

    class Person { public:Person(const string name, const int age): m_Name(name), m_Age(age){cout << "constructor" << endl;}string m_Name;int m_Age; };template <class T> bool myCampare(T& a, T& b) {if (a == b) {return true;}else {return false;} }// Person 不能對(duì)比 // 解決方法有兩種 // 1、重載 "==" 運(yùn)算符, 太過麻煩 // 2、利用具體化Person的版本實(shí)現(xiàn), 具體化會(huì)優(yōu)先調(diào)用 // 具體化實(shí)現(xiàn) template<> bool myCampare(Person& a, Person& b) {if (a.m_Age == b.m_Age && a.m_Name == b.m_Name) {return true;}else {return false;} }int main() {int a = 10;int b = 20;bool ret = myCampare(a, b);cout << ret << endl;Person pa("Tom", 18);Person pb("Tom", 18);bool pret = myCampare(pa, pb);cout << pret << endl;return 0; }

    總結(jié):

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

    • 學(xué)習(xí)模板并不是為了寫模板,而是在STL庫(kù)中能夠運(yùn)用系統(tǒng)提供的模板

    1.8 類模板

    類模板作用:

    • 建立一個(gè)通用類,類中的成員 數(shù)據(jù)類型 可以不具體指定,用一個(gè)虛擬的類型來代表。
    // 類模板 template<class NameType, class AgeType> class Person { public:Person(NameType name, AgeType age) {this->m_Name = name;this->m_Age = age;}void showPerson() {cout << this->m_Name << this->m_Age << endl;}NameType m_Name;AgeType m_Age;}; int main() {Person<string, int> p1("悟空", 999);p1.showPerson();return 0; }

    1.9 類模板與函數(shù)模板的區(qū)別

    主要有兩點(diǎn)區(qū)別:

    • 類模板沒有自動(dòng)類型推導(dǎo)的使用方式,只有顯式指定類型方式
    • 類模板在模板參數(shù)列表 <> 中可以有默認(rèn)參數(shù)
    template<class NameType, class AgeType = int> // 使用默認(rèn)參數(shù)

    1.10 類模板中成員函數(shù)創(chuàng)建時(shí)機(jī)

    與普通類中成員函數(shù)創(chuàng)建時(shí)機(jī)是有區(qū)別的:

    • 普通類中的成員函數(shù)一開始就可以創(chuàng)建
    • 類模板中的成員函數(shù)并不是在一開始就創(chuàng)建,而是在調(diào)用時(shí)才創(chuàng)建

    1.11 類模板對(duì)象做函數(shù)參數(shù)

    類模板實(shí)例化出對(duì)象,向函數(shù)傳參的方式有三種:

  • 指定傳入的類型 — 直接顯式對(duì)象的數(shù)據(jù)類型 — 最常用方式
  • 參數(shù)模板化 — 將對(duì)象中的參數(shù)變?yōu)槟0暹M(jìn)行傳遞
  • 整個(gè)類模板化 – 將這個(gè)對(duì)象類型 模板化進(jìn)行傳遞
  • template<class NameType, class AgeType> class Person { public:Person(NameType name, AgeType age) {this->m_Name = name;this->m_Age = age;}void showPerson() {cout << "姓名:" <<this->m_Name <<" 年齡:" << this->m_Age << endl;}NameType m_Name;AgeType m_Age; }; //1. 指定傳入的類型-- - 直接顯式對(duì)象的數(shù)據(jù)類型 void printPerson1(Person<string, int> &p) {p.showPerson(); } //2. 參數(shù)模板化-- - 將對(duì)象中的參數(shù)變?yōu)槟0暹M(jìn)行傳遞 template <class NameType, class AgeType> void printPerson2(Person<NameType,AgeType>& p) {cout << "NameType的類型" << typeid(NameType).name() << endl; // 查看數(shù)據(jù)類型p.showPerson(); }//3. 整個(gè)類模板化 -- 將這個(gè) 對(duì)象類型 模板化進(jìn)行傳遞 template <class T> void printPerson3(T & p) {cout << "T的類型" << typeid(T).name() << endl; // 查看數(shù)據(jù)類型 Personp.showPerson(); }int main() {Person<string, int> p1("悟空", 999);printPerson1(p1);Person<string, int> p2("八戒", 109);printPerson2(p2);Person<string, int> p3("沙僧", 9);printPerson3(p3);return 0; }

    1.12 類模板與繼承

    當(dāng)類模板遇到繼承時(shí),需要注意以下幾點(diǎn):

    • 當(dāng)子類繼承的父類是一個(gè)類模板時(shí),子類在聲明的時(shí)候,需要指定出父類中T的類型
    • 如果不指定,編譯器無法給子類分配內(nèi)存
    • 如果想靈活的指定出父類中T的類型,子類也需要變?yōu)轭惸0?/li>
    template<class T> class Base { public:T m; }; //class Derived : public Base{ // 必須要知道父類中的T類型,才能繼承給子類// 制定出父類中的成員類型 class Derived: public Base<int> { };// 如果想要靈活的指定父類中的T類型,子類也需要變?yōu)轭惸0?template<class T1, class T2> class Derived2 : public Base<T1> { public:Derived2() {cout << "T1 數(shù)據(jù)類型: " << typeid(T1).name() << endl;cout << "T2 數(shù)據(jù)類型: " << typeid(T2).name() << endl;}T2 obj; };int main() {Derived2<int, char> d2;return 0; }

    1.12 類模板的成員函數(shù)的類外實(shí)現(xiàn)

    類外實(shí)現(xiàn):

    template<class T1, class T2> class Person { public:Person(T1 name, T2 age);void showPerson();T1 m_Name;T2 m_Age; }; // 構(gòu)造函數(shù)類外實(shí)現(xiàn) template<class T1, class T2> Person<T1, T2>::Person(T1 name, T2 age) {this->m_Name = name;this->m_Age = age; } // 成員函數(shù)類外實(shí)現(xiàn) template<class T1, class T2> void Person<T1, T2>::showPerson() {cout << "姓名:" << this->m_Name << " 年齡:" << this->m_Age << endl; }int main() {Person<string, int>p1("Tom", 21);p1.showPerson();return 0; }

    1.13 類模板的分文件編寫

    學(xué)習(xí)目標(biāo):

    • 掌握類模板成員函數(shù) 分文件編寫 產(chǎn)生的問題以及解決方式

    問題:

    • 類模板中成員函數(shù)創(chuàng)建時(shí)機(jī)是在調(diào)用階段,導(dǎo)致分文件編寫時(shí)鏈接不到

    解決:

    • 解決方式1:直接包含.cpp源文件

    • 解決方式2:將聲明和實(shí)現(xiàn)寫到同一個(gè)文件中,并更改后綴名為.hpp,hpp是約定的名稱,并不是強(qiáng)制

    解決方式1

    #include "Person.cpp"

    解決方式2

    // Person.hpp #pragma once#include<iostream> #include <string> using namespace std;template<class T1, class T2> class Person { public:Person(T1 name, T2 age);void showPerson();T1 m_Name;T2 m_Age; };// 構(gòu)造函數(shù)類外實(shí)現(xiàn) template<class T1, class T2> Person<T1, T2>::Person(T1 name, T2 age) {this->m_Name = name;this->m_Age = age; } // 成員函數(shù)類外實(shí)現(xiàn) template<class T1, class T2> void Person<T1, T2>::showPerson() {cout << "姓名:" << this->m_Name << " 年齡:" << this->m_Age << endl; } // main.cpp #include<iostream> #include <string> using namespace std; // 第一種解決方式(很少采用),直接包含 頭文件Person.h 改成源文件 Person.cpp。 // #include"Person.cpp" // 第二種解決方式, 將.h 和.cpp內(nèi)容寫到一起,將后綴名改為.hpp文件; #include"Person.hpp"int main() {Person<string, int>p1("Tom", 21);p1.showPerson();return 0; }

    1.13 類模板與友元

    學(xué)習(xí)目標(biāo):

    • 掌握類模板配合友元函數(shù)的類內(nèi)和類外實(shí)現(xiàn)

    全局函數(shù) 類內(nèi) 實(shí)現(xiàn) – 直接在類內(nèi)聲明友元即可

    全局函數(shù) 類外 實(shí)現(xiàn) – 需要提前讓編譯器知道全局函數(shù)的存在

    template<class T1, class T2> // Person模板類聲明 class Person; // 讓編譯器看到下面函數(shù)中的Person類 // 全局函數(shù) 類外實(shí)現(xiàn) 實(shí)現(xiàn)部分 要放在前面 讓編譯器知道 template<class T1, class T2> void printPerson2(Person<T1, T2> p) { // 全局函數(shù) 不用加Person作用域cout << "全局函數(shù) 類外實(shí)現(xiàn) /n 姓名: " << p.m_Name << " 年齡: " << p.m_Age << endl; }template<class T1, class T2> class Person { public:Person(T1 name, T2 age) {this->m_Name = name;this->m_Age = age;}// 全局函數(shù) 類內(nèi)實(shí)現(xiàn)friend void printPerson(Person<T1, T2> p) {cout << "全局函數(shù) 類內(nèi)實(shí)現(xiàn)/n 姓名: " << p.m_Name << " 年齡: " << p.m_Age << endl;}// 全局函數(shù) 類外實(shí)現(xiàn) 聲明部分// printPerson2后 加 空模板的參數(shù)列表// 如果全局函數(shù) 是類外實(shí)現(xiàn),需要讓編譯器提前知道該全局函數(shù)的實(shí)現(xiàn)friend void printPerson2<>(Person<T1, T2> p); // 普通函數(shù)的聲明private:T1 m_Name;T2 m_Age; };int main() {// 1.全局函數(shù)在類內(nèi)實(shí)現(xiàn)Person<string, int> p("Tom", 21);printPerson(p);printPerson2(p);return 0; }

    總結(jié):建議全局函數(shù)做類內(nèi)實(shí)現(xiàn),用法簡(jiǎn)單,而且編譯器可以直接識(shí)別。如果不將全局函數(shù)提前,可以使用全函數(shù)的聲明

    1.13 案例實(shí)現(xiàn)一個(gè)通用的數(shù)組類

    要求如下:

    • 可以對(duì)內(nèi)置數(shù)據(jù)類型以及自定義類型的數(shù)據(jù)進(jìn)行存儲(chǔ)
    • 將數(shù)組中的數(shù)據(jù)存儲(chǔ)到堆區(qū)
    • 構(gòu)造函數(shù)中可以傳入數(shù)組的容量
    • 提供對(duì)應(yīng)的拷貝構(gòu)造函數(shù)以及**operator=**防止淺拷貝問題
    • 提供尾插法和尾刪法對(duì)數(shù)組中的數(shù)據(jù)進(jìn)行增加和刪除
    • 可以通過下標(biāo)的方式訪問數(shù)組中的元素
    • 可以獲取數(shù)組中當(dāng)前元素個(gè)數(shù)和數(shù)組的容量

    2、STL 初識(shí)

    • C++的面向?qū)ο蠛头盒途幊趟枷?#xff0c;目的就是復(fù)用性的提升
    • 為了建立數(shù)據(jù)結(jié)構(gòu)和算法的一套標(biāo)準(zhǔn),誕生了STL

    2.1 STL基本概念

    • STL(Standard Template Library, 標(biāo)準(zhǔn)模板庫(kù) )
    • STL從廣義上分為:容器(container) 算法(algorithm) 迭代器(iterator)
    • 容器算法 之間通過 迭代器 進(jìn)行無縫連接
    • STL幾乎所有代碼都采用了模板類或者模板函數(shù)

    2.2 STL六大組件

    STL大體分為六大組件,分別是 容器算法迭代器仿函數(shù)適配器(配接器)、空間配置器

  • 容器:各種數(shù)據(jù)結(jié)構(gòu),如vector、list、deque、set、map等,用來存放數(shù)據(jù)
  • 算法:各種常用算法,如sort、find、copy、for_each等
  • 迭代器:扮演了容器和算法之間的膠合劑
  • 仿函數(shù):行為類似函數(shù),可作為算法的某種策略
  • 適配器:一種用來修飾容器或者仿函數(shù)或迭代器接口的東西
  • 空間配置器:負(fù)責(zé)空間的配置與管理
  • 2.3 STL中容器、算法、迭代器

    容器:置物之所也

    STL容器就是將運(yùn)用最廣泛的一些 數(shù)據(jù)結(jié)構(gòu) 實(shí)現(xiàn)出來

    常用的數(shù)據(jù)結(jié)構(gòu):數(shù)組,鏈表,樹,棧,隊(duì)列,集合,映射表等

    這些容器分為序列容器和關(guān)聯(lián)式容器兩種:

    • 序列式容器:強(qiáng)調(diào) 的排序,序列式容器中的每個(gè)元素均有固定的位置
    • 關(guān)聯(lián)式容器:二叉樹結(jié)構(gòu),各元素之間沒有嚴(yán)格的物理上順序關(guān)系

    算法:問題之解法也

    有限的步驟,解決邏輯或數(shù)學(xué)上的問題,這一門學(xué)科我們叫做算法

    算法分為:質(zhì)變算法非質(zhì)變算法

    質(zhì)變算法:是指運(yùn)算過程中會(huì)更改區(qū)間內(nèi)元素的內(nèi)容。例如拷貝、替換、刪除等等

    非質(zhì)變算法:是指運(yùn)算過程中不會(huì)更改區(qū)間內(nèi)的元素內(nèi)容,例如查找、計(jì)數(shù)、遍歷、尋找極值等等

    迭代器:容器和算法之間的膠合劑

    提供一種方法,使之能夠依序訪問某個(gè)容器所含的各個(gè)元素,而又無需暴露該容器內(nèi)部表示方式。

    每個(gè)容器都有自己專屬迭代器

    迭代器使用非常類似與指針,初學(xué)階段我們可以先理解為指針

    迭代器種類:

    種類功能支持運(yùn)算
    輸入迭代器對(duì)數(shù)據(jù)的只讀訪問只讀,支持++、==、!=
    輸出迭代器對(duì)數(shù)據(jù)的只寫訪問只寫,支持++
    前向迭代器讀寫操作,并能向前推進(jìn)迭代器讀寫,支持++、==、!=
    雙向迭代器讀寫操作,并能向前向和后操作讀寫,支持++、–
    隨機(jī)訪問迭代器讀寫操作,可以以跳躍的方式訪問任意數(shù)據(jù),功能最強(qiáng)的迭代器讀寫,支持++、–、[n]、-n、<、<=、>、>=

    常用的容器中迭代器種類為雙向迭代器、隨機(jī)訪問迭代器。

    2.4 容器算法迭代器初識(shí)

    STL中最常用的容器為vector,可以理解為數(shù)組

    vector存放內(nèi)置數(shù)據(jù)類型

    容器: vector

    算法:for_each

    迭代器:vector<int>::iterator

    #include<iostream> using namespace std; #include<vector> #include<algorithm>void myPrint(int val) { // 供第三種遍歷方法的for_each使用cout << val << endl; }int main() {// 創(chuàng)建vector容器vector<int> v;// 向容器中插入數(shù)據(jù)v.push_back(10);v.push_back(20);v.push_back(30);v.push_back(40);// 通過迭代器訪問容器中的數(shù)據(jù)// 起始迭代器 指向容器中的 第一個(gè)元素vector<int>::iterator itBegin = v.begin(); // 結(jié)束迭代器 指向容器中最后一個(gè)元素的下一個(gè)位置vector<int>::iterator itEnd = v.end(); // 第一種遍歷方式while (itBegin != itEnd) {cout << *itBegin << endl; // 使用*解引用itBegin++;}// 第二種遍歷方式 常用for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {cout << *it << endl;}// 第三種遍歷方式 使用Algorithm 中 for_each 算法for_each(v.begin(), v.end(), myPrint); }

    vector存放自定義數(shù)據(jù)類型

    class Person { public:Person(string name, int age) {this->m_Name = name;this->m_Age = age;}string m_Name;int m_Age; };// 存放Person類型 void test1() {// 創(chuàng)建vector容器vector<Person> v;// Person類型Person p1("Tom", 16);Person p2("Tom1", 116);Person p3("Tom2", 216);Person p4("Tom3", 316);Person p5("Tom4", 416);// 向容器中插入數(shù)據(jù)v.push_back(p1);v.push_back(p2);v.push_back(p3);v.push_back(p4);v.push_back(p5);for (vector<Person>::iterator it = v.begin(); it != v.end(); it++) {// (*it) 是Person對(duì)象cout << "姓名:" << (*it).m_Name << " 年齡:" << (*it).m_Age << endl;cout << "姓名:" << it->m_Name << " 年齡:" << it->m_Age << endl;} }// 存放Person類型指針 void test2() {// 創(chuàng)建vector容器vector<Person *> v;// Person類型Person p1("Tom", 16);Person p2("Tom1", 116);Person p3("Tom2", 216);Person p4("Tom3", 316);Person p5("Tom4", 416);// 向容器中插入數(shù)據(jù)v.push_back(&p1);v.push_back(&p2);v.push_back(&p3);v.push_back(&p4);v.push_back(&p5);for (vector<Person *>::iterator it = v.begin(); it != v.end(); it++) {// *it 是指針 訪問Person中的屬性 要用 (*it)->m_Namecout << "姓名:" << (*it)->m_Name << " 年齡:" << (*it)->m_Age << endl;} } int main() {test1();test2();return 0; }

    vector容器嵌套容器

    容器中嵌套容器, 然后遍歷輸出

    int main() {// 容器嵌套容器vector<vector<int>> v;// 創(chuàng)建小容器 v1;vector<int> v1;vector<int> v2;vector<int> v3;vector<int> v4;for (int i = 0; i < 4; i++) {v1.push_back(i+1);v2.push_back(i+2);v3.push_back(i+3);v4.push_back(i+4);}v.push_back(v1);v.push_back(v2);v.push_back(v3);v.push_back(v4);for (vector<vector<int>>::iterator it = v.begin(); it != v.end(); it++) { // 判斷條件用!= 或者 < 都可以// (*it) -- 容器 vector<int>for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++) {cout << (*vit) << "\t";}cout << endl;}return 0; }

    3、STL – 常用容器

    常用容器有,string、vector、deque、stack、 queue、list、set/multiset、map/multimap。

    3.1 String 容器

    1. 基本概念:

    本質(zhì):string 是 C++ 風(fēng)格的字符串, 而string本質(zhì)上是一個(gè)類

    string和char*的 區(qū)別

    • char * 是一個(gè)指針
    • string 是一個(gè)類,類內(nèi)部封裝了char*,管理這個(gè)字符串,是一個(gè) char * 型的的容器

    特點(diǎn)

    string 類內(nèi)部封裝了很多成員方法

    例如: 查找find, 拷貝copy,刪除delete, 替換replace, 插入insert

    string 管理 char*所分配的內(nèi)存,不用擔(dān)心復(fù)制越界和取值越界,由類內(nèi)部進(jìn)行負(fù)責(zé)

    2. string構(gòu)造函數(shù)

    構(gòu)造函數(shù)原型

    • string(); // 創(chuàng)建一個(gè)空的字符串 例如: string str;
    • string(const char * s) // 使字符串s初始化
    • string(const string & str); // 使用一個(gè)string對(duì)象初始化另一個(gè)string對(duì)象
    • string(int n, char c); // 使用n個(gè)字符c初始化
    string s1; //默認(rèn)構(gòu)造const char* str = "hello world"; string s2(str); cout << "s2 = " << s2 << endl;string s3(s2); cout << "s3 = " << s3 << endl;string s4(5, 'c'); cout << "s4 = " << s4 << endl;

    3. string 賦值操作

    給string字符串進(jìn)行賦值

    賦值函數(shù)原型

    • string& operator=(const char *s); // char * 類型字符串 賦值 給當(dāng)前字符串
    • string& operator=(const string &s); // 把字符串s賦給當(dāng)前的字符串
    • string& operator=(char c); // 字符賦值給當(dāng)前的字符串
    • strin& assign(const char*s); // 把字符串s賦值給當(dāng)前的字符串
    • string& assign(const char *s, int n); // 把字符串s的前n個(gè)字符賦給當(dāng)前的字符串
    • string & assign(const string &s); //把字符串s賦給當(dāng)前字符串
    • string& assign(int n, char c); //用n個(gè)字符c賦給當(dāng)前字符串
    string str1; str1 = "hello world"; cout << "str1 = " << str1 << endl; string str2 = str1; cout << "str2 = " << str2 << endl; string str3; str3 = 'c'; cout << "str3 = " << str3 << endl;string str4; str4.assign("hello C++"); cout << "str4 = " << str4 << endl;string str5; str5.assign(str1, 5); cout << "str5 = " << str5 << endl;string str6; str6.assign(str1); cout << "str6 = " << str6 << endl;string str7; str7.assign(10,'h'); cout << "str7 = " << str7 << endl;

    總結(jié):string 賦值方法有很多,operator=更實(shí)用。

    4. string字符串拼接

    實(shí)現(xiàn)在字符串末尾拼接字符串

    函數(shù)原型:

    • string& operator+=(const char* str); // 重載+=運(yùn)算符
    • string& operator+=(const char* c);
    • string& operator+=(const string& str);
    • string& append(const char *s); //把字符串s連接到當(dāng)前字符串結(jié)尾
    • string& append(const char *s, int n); //把字符串s前n個(gè)字符連接到當(dāng)前字符串結(jié)尾
    • string& append(const string &s); // 與第三個(gè)相同
    • string& append(const string &s, int pos, int n); // 把字符串s從pos開始的n個(gè)字符連接到字符串結(jié)尾。 pos是位置,從0開始
    string str1; str1 = "我"; str1 += "不要玩游戲"; cout << "str1 = " << str1 << endl; str1 += ':'; // 字符 string str2 = "王者榮耀"; str1 += str2; cout << "str1 = " << str1 << endl;string str3 = "i"; str3.append("love ");str3.append("game over", 4); // 注意一個(gè)漢字占兩個(gè)字符 cout << "str3 = " << str3 << endl; str3.append("ksfs honor sdf", 4, 6); cout << "str3 = " << str3 << endl;

    5.字符串查找替換

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

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

    函數(shù)原型

    • int find(const string& str, int pos = 0) const; // 常函數(shù), 查找str第一次出現(xiàn)位置,從pos開始查找
    • int find(const char* s, int pos =0) const; // 查找s第一次出現(xiàn)的位置,從pos位置開始查找
    • int find(const char*s, int pos, int n) const; // 從pos位置查找s前n個(gè)字符第一次位置
    • int find(const char c, int pos = 0) const; // 查找字符c第一次出現(xiàn)的位置
    • int rfind(const string& str, int pos = npos) const; // 查找str 最后一次位置, 從pos開始查找
    • int rfind(const char* s, int pos = npos) const; //查找s最后一次出現(xiàn)位置,從pos=npos開始查找,從右往左數(shù)npos個(gè)元素,查找是正向的
    • int rfind(const char* s, int pos, int n) const;// 從pos位置查找s的前n個(gè)字符最后一次位置
    • int rfind(const char c, int pos=0) const; // 查找字符c最后一次出現(xiàn)位置
    • string& replace(int pos, int n, const string& str); // 替換從pos開始n個(gè)字符為字符串str
    • string& replace(int pos, int n, const char*s);//替換從pos開始的n個(gè)字符為字符串s
    string str="hello hello yaaya "; int pos = str.find("hello", 5); int rpos = str.rfind("hello", 5); str.replace(1,2,"3sdsfgs") // 從1號(hào)位置起,2個(gè)字符,替換為“3sdsfgs”

    6. 字符串比較

    字符串之間的比較,主要用于判斷兩個(gè)字符串是否相等

    • 字符串按字符的ASCII碼進(jìn)行對(duì)比。ASCII碼大小,a<z

    = 返回 0

    > 返回 1

    < 返回-1

    函數(shù)原型

    • int compare(const string& s) const; //與字符串s比較
    • int compare(const char* s) const; // 與字符串s比較
    string str1 = "china"; string str2 = "american" int ret = str1.compare(str2);

    7. 字符存取

    string中單字符存取方式有兩種

    • char& operator[](int n); //通過[]方式取字符
    • char& at(int n); // 通過at方法獲取字符
    // 獲取字符串長(zhǎng)度 str.size(); str[1]; str.at(1);

    8. 字符串插入和刪除

    對(duì)string字符串進(jìn)行插入和刪除字符操作

    • string& insert(int pos, const char* s); //插入字符串
    • string& insert(int pos, const string& str); //插入字符串
    • string& insert(int pos, int n, char c); // 在指定位置插入n個(gè)字符c
    • string& erase(int pos, int n = npos); //刪除從pos開始的n個(gè)字符
    string str = "hello"; // 插入 str.insert(1, "111"); // 刪除 str.erase(1, 3);

    9. 子串獲取

    從字符串中獲取想要的子串

    • 從字符串中獲取想要的子串

    函數(shù)原型:

    • string substr(int pos=0, int n = pos) const; // 返回由pos開始的n個(gè)字符組成的字符串
    str.substr(1,3);

    總結(jié):可以跟其他查找成員函數(shù)配合,如find等來截取特定子串

    3.2 vector容器

    1. Vector基本概念

    功能

    • vector數(shù)據(jù)結(jié)構(gòu)和數(shù)組非常相似,也稱為單端數(shù)組

    與普通數(shù)組的區(qū)別

    • 不同之處在于數(shù)組是靜態(tài)空間,而vector可以動(dòng)態(tài)擴(kuò)展

    動(dòng)態(tài)擴(kuò)展:

    • 不是在原空間之后續(xù)接新空間,而是找更大的連續(xù)內(nèi)存空間,然后將原數(shù)據(jù)拷貝新空間,釋放原空間

    vector容器的迭代器是支持隨機(jī)訪問的迭代器。 begin()、end()、rbegin()、 rend()

    函數(shù)原型

    • vector<T> v; //采用模板實(shí)現(xiàn)類實(shí)現(xiàn),默認(rèn)構(gòu)造函數(shù)
    • vector(v.begin(), v.end()); // 將v[begin(), end()) 左閉右開區(qū)間中的元素拷貝給本身,因?yàn)閑nd()是指向最后一個(gè)元素的下一個(gè)位置
    • vector(n, elem); // 構(gòu)造函數(shù)將n個(gè)elem拷貝給本身
    • vector(const vector &vec); // 拷貝構(gòu)造函數(shù)
    vector<int> v; v.push_back(10); vector<int> v(10, 100);

    2.vector的賦值操作

    函數(shù)原型

    • vector& operator=(const vector &vec); // 重載等號(hào)操作符
    • assign(beg, end); // 將[beg, end)區(qū)間中的數(shù)據(jù)拷貝賦值給本身
    • assign(n, elem); // 將n個(gè)elem拷貝賦值給本身
    vector<int> v(10,5); vector<int> v2; v2 = v; v2.assign(v.begin(), v.end()); v2.assign(10,100);

    3.vector容量和大小

    對(duì)vector容器的容量和大小的操作

    函數(shù)原型

    • empty(); // 判斷容器是否為空
    • capacity(); //容器的容量
    • size(); // 返回容器中元素的個(gè)數(shù)
    • resize(int num); // 重新指定容器的長(zhǎng)度為num, 若容器邊長(zhǎng),則以默認(rèn)值填充新位置, 如果容器變短,則末尾超出容器長(zhǎng)度的元素被刪除
    • resize(int num, elem); // 重新指定容器的長(zhǎng)度為num, 若容器邊長(zhǎng), 則以elem值填充新位置,如果容器變短,則末尾超出容器長(zhǎng)度的元素被刪除
    vector<int> v1; v1.empty(); v1.capacity(); // 容量 永遠(yuǎn)都大于等于 size(); 隨著插入操作會(huì)動(dòng)態(tài)變大 v1.size(); v1.resize(10); v1.resize(10, 100);

    4. vector插入與刪除

    函數(shù)原型

    • push_back(elem) //尾部插入元素elem
    • pop_back() // 刪除最后一個(gè)元素
    • insert(const_interator pos, elem) //迭代器指向位置pos插入元素elem
    • insert(const_interator pos, int count, elem) //迭代器指向位置pos插入count個(gè)元素elem
    • erase(const_iterator pos) // 刪除迭代器指向的元素
    • erase(const_iterator start, const_iterator end) // 刪除迭代器從start到end之間的元素
    • clear();
    void printVector(vector<int>& v) {for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {cout << (*it) << "\t";}cout << endl; } int main() {vector<int> v1;v1.push_back(10);v1.push_back(20);v1.push_back(30);v1.push_back(40);v1.push_back(50);printVector(v1);v1.pop_back();printVector(v1);// 插入 第一個(gè)參數(shù)是迭代器v1.insert(v1.begin(), 200);printVector(v1);v1.insert(++v1.begin(), 2, 100);printVector(v1);// 刪除v1.erase(v1.begin());printVector(v1);// 清空 v1.erase(v1.begin(), v1.end());v1.clear();printVector(v1);return 0; }

    5. vector數(shù)據(jù)存取

    對(duì)vector中數(shù)據(jù)的存取操作

    函數(shù)原型

    • at(int idx) //返回索引 idx 所指的數(shù)據(jù)
    • operator[] // 返回索引 idx 所指的數(shù)據(jù)
    • front() // 返回容器中第一個(gè)數(shù)據(jù)元素
    • back() // 返回容器中最后一個(gè)數(shù)據(jù)元素
    vector<int> v1; v1.push_back(10); v1.push_back(20); v1.push_back(4);v1.at(0); v1[2];v1.front(); v1.back();

    6. vector互換容器

    實(shí)現(xiàn)兩個(gè)容器內(nèi)元素進(jìn)行互換

    函數(shù)原型

    • swap(vec); // 將vec中元素與本身的元素互換
    int main() {vector<int> v1;for (int i = 0; i < 10; i++) {v1.push_back(i);}vector<int> v2;for (int i = 9; i >=0 ; i--) {v2.push_back(i);}printVector(v1);printVector(v2);v1.swap(v2);printVector(v1);printVector(v2);// 2、 swap的實(shí)際用途// 巧用swap可以收縮內(nèi)存空間vector<int> v;for (int i = 0; i < 100000; i++) {v1.push_back(i);}v1.resize(3); // capacity不會(huì)被更改 因此存在內(nèi)存浪費(fèi)cout << v1.capacity() << endl;cout << v1.size() << endl;//swap配合匿名對(duì)象收縮內(nèi)存vector<int>(v).swap(v); // vector<int>(v) 使用拷貝構(gòu)造匿名對(duì)象// 匿名對(duì)象在當(dāng)前行執(zhí)行完成后 由系統(tǒng)回收其占用內(nèi)存cout << v1.capacity() << endl;cout << v1.size() << endl;return 0; }

    總結(jié):可以利用swap收縮內(nèi)存

    7. 預(yù)留空間

    功能:減少vector在動(dòng)態(tài)擴(kuò)展容量時(shí)的擴(kuò)展次數(shù)

    函數(shù)原型:reserve(int len); //容器預(yù)留len個(gè)元素長(zhǎng)度,預(yù)留位置不初始化,元素不可訪問

    注意是reserve 預(yù)留 不是 reverse 反轉(zhuǎn)

    vector<int> v1; v1.reserve(100000); int* p = nullptr; int num = 0; cout << v1.capacity() << endl; // 100000 for (int i = 0; i < 100000; i++) {v1.push_back(i);if (p != &v1[0]) {p = &v1[0];num++;} } cout << num << endl;

    3.3 deque容器

    1. 基本概念

    功能:

    雙端數(shù)組,可以對(duì) 頭端和尾端 進(jìn)行插入刪除操作

    deque與vector區(qū)別:

    • vector 對(duì)于頭部插入刪除效率低,數(shù)據(jù)量越大,效率越低
    • deque相對(duì)而言,對(duì)頭部插入刪除速度會(huì)比vector快
    • vector訪問元素時(shí)的速度會(huì)比deque快,這和兩者內(nèi)部實(shí)現(xiàn)相關(guān)

    deque內(nèi)部工作原理

    deque內(nèi)部有個(gè)中控器,維護(hù)每段緩沖區(qū)的內(nèi)容,緩沖區(qū)存放真實(shí)數(shù)據(jù)。

    中控器維護(hù)的是每個(gè)緩沖區(qū)的地址,使得使用deque時(shí) 一片連續(xù)的內(nèi)存空間

    (原理才想,鏈表,鏈接接多個(gè)成塊的內(nèi)存空間)

    • deque容器的迭代器也是支持隨機(jī)訪問
    // 注意 只讀迭代器 的使用 /* 注意傳入如果const修飾的常量 迭代器要用const_iterator 最簡(jiǎn)單的是用auto,學(xué)習(xí)最好不用 void printDeque(const deque<int>& d) {for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) {cout << *it << "\t";}cout << endl; } */ #include<deque> void printDeque(const deque<int>& d) {for (auto it = d.begin(); it != d.end(); it++) {cout << *it << "\t";}cout << endl; }int main() {deque<int> d1; // 默認(rèn)構(gòu)造for (int i = 0; i < 10;i++) {d1.push_back(i);}printDeque(d1);deque<int> d2(d1.begin(), d1.end());printDeque(d2);deque<int> d3(10, 100);printDeque(d3);deque<int> d4(d3);printDeque(d4);for (int i = 0; i < 10;i++) {d1.push_front(i);}printDeque(d1);return 0; }

    2. deque賦值操作

    函數(shù)原型

    • deque& operator=(const deque & deq) //重載等號(hào)操作符
    • assign(beg, end) // 將[beg, end)區(qū)間的數(shù)據(jù)拷貝賦值給本身
    • assign(n, elem) // 將n個(gè)elem拷貝賦值給本身
    deque<int> d1; // operator = deque<int> d2 = d1; // assign(beg, end) deque<int> d3; d3.assign(d1.begin(), d1.end()); // assign(n, elem) deque<int> d4; d4.assign(10,100); // 10個(gè)100

    3.deque大小操作

    對(duì)deque容器的大小進(jìn)行操作

    函數(shù)原型:

    • deque.empty()
    • deque.size()
    • deque.resize(num)
    • deque.resize(num, elem)

    注意: deque沒有容量capacity的成員

    4. deque插入和刪除

    函數(shù)原型:

    兩端插入:

    • push_back(elem)
    • push_front(elem) // 從容器頭部插入一個(gè)數(shù)據(jù) , 注意次序
    • pop_back(elem)
    • pop_front(elem)

    指定位置操作:

    • insert(pos, elem)
    • insert(pos, n, elem)
    • insert(pos, beg, end)
    • clear()
    • erase(beg, end)
    • erase(pos)

    5. deque數(shù)據(jù)存取

    對(duì)deque中數(shù)據(jù)的存取操作

    函數(shù)原型

    • at(int idx)
    • operator[]
    • front()
    • back();

    6. deque排序

    算法:

    • sort(iterator brg, iterator end);// 對(duì)beg到end區(qū)間內(nèi)元素進(jìn)行排序
    • 對(duì)于支持隨機(jī)訪問的迭代器容器,都可以利用sort算法直接對(duì)其進(jìn)行排序
    sort(d.begin(), d.end());

    3.4 STL評(píng)委打分案例

    案例描述

    有五名選手,選手ABCDE,10個(gè)評(píng)委分別對(duì)每一名選手打分,去掉最高分和最低分,取平均分。

    實(shí)現(xiàn)步驟

  • 創(chuàng)建五名選手, 放到vector中
  • 遍歷vector容器,取出來每一個(gè)選手,執(zhí)行for循環(huán),可以把10個(gè)評(píng)分打分存在deque容器中
  • sort算法對(duì)deque容器中分?jǐn)?shù)排序,去除最高和最低分
  • deque容器遍歷一遍,累加總分
  • 獲取平均分
  • class Person { public:Person(string name, int score): m_Name(name), m_Score(score) {}string m_Name;double m_Score; };void printPerson(const vector<Person>& v) {for (vector<Person>::const_iterator it = v.begin(); it != v.end(); it++) {cout <<"姓名:" << it->m_Name << " 分?jǐn)?shù):"<< it->m_Score << "\t";cout << endl;}}void creatPerson(vector<Person>& v) {string nameSeed = "ABCDE";for (int i = 0; i < 5; i++) {string name = "選手";name += nameSeed[i];Person p(name, 0);v.push_back(p);} }void setScore(vector<Person>& v) {for (vector<Person>::iterator vit = v.begin(); vit != v.end(); vit++) {deque<int> d;for (int i = 0; i < 10; i++) {d.push_back(rand() % 41 + 60);}sort(d.begin(), d.end());d.pop_front();d.pop_back();int sum = 0;for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) {sum += *it;}vit->m_Score = (double)sum/ d.size();} }int main() {// 創(chuàng)建5名選手vector<Person> v;// 給 5名選手 賦初值creatPerson(v);printPerson(v);// 評(píng)委打分 隨機(jī)數(shù)srand((unsigned int)time(nullptr));setScore(v);printPerson(v);return 0; }

    3.5 stack容器 棧容器

    1. 基本概念

    stack 是一種先進(jìn)后出(FILO)的數(shù)據(jù)結(jié)構(gòu),它只有一個(gè)出口。

    [外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-JzSXhZgy-1599351751836)(C:\Users\ypw\AppData\Roaming\Typora\typora-user-images\image-20200904204744032.png)]

    棧中只有頂端的元素才可以被外界使用,因此棧不允許有遍歷行為。

    2. stack常用接口

    構(gòu)造函數(shù):

    • stack<T> stk
    • stack(const stack &stk);

    賦值操作

    • stack& operator=(const stack& stk)

    數(shù)據(jù)存取

    • push(elem)
    • pop() // 從棧頂移除第一個(gè)元素
    • top() // 返回棧頂元素

    大小操作

    • empty()
    • size() // 返回棧的大小
    stack<int> stk; stk.push(1); stk.push(2); stk.push(3); cout << stk.size() << endl; while (!stk.empty()) {cout << stk.top() << endl;stk.pop(); }

    3.6 queue 容器 隊(duì)列

    Queue是一種先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)

    隊(duì)列容器只有隊(duì)頭和隊(duì)尾才可以被外界使用,因此隊(duì)列不允許有遍歷行為。

    常用接口

    構(gòu)造函數(shù):

    • queue<T> q
    • queue(const queue& q)

    賦值操作:

    • queue& operator=(const queue &q)

    數(shù)據(jù)存取:

    • push(elem)
    • pop()
    • back() 返回最后一個(gè)元素
    • front()

    大小操作:

    • empty()
    • size()

    3.7 list容器 鏈表

    1. 基本概念

    功能:將數(shù)據(jù)進(jìn)行鏈?zhǔn)酱鎯?chǔ),可以在任意位置上進(jìn)行快速插入或刪除元素

    鏈表(list):是一種物理存儲(chǔ)單元上非連續(xù)的存儲(chǔ)結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序是通過鏈表中的指針鏈接實(shí)現(xiàn)的

    鏈表的組成: 鏈表由一系列的 結(jié)點(diǎn) 組成

    結(jié)點(diǎn): 一個(gè)是存儲(chǔ)數(shù)據(jù)元素的數(shù)據(jù)域,另一個(gè)是存儲(chǔ)下一個(gè)結(jié)點(diǎn)地址的指針域

    STL中的鏈表是一個(gè) 雙向循環(huán)鏈表

    優(yōu)點(diǎn):

    • 采用動(dòng)態(tài)存儲(chǔ)分配,不會(huì)造成內(nèi)存浪費(fèi)和溢出
    • 鏈表執(zhí)行插入和刪除操作十分方便,修改指針即可,不需要移動(dòng)大量元素

    缺點(diǎn):

    • 容器遍歷速度,沒有數(shù)組快
    • 占用空間比數(shù)組大,因?yàn)椴粌H包含數(shù)據(jù)域還包含指針域 指針4位

    性質(zhì): 插入操作和刪除操作都不會(huì)造成原有l(wèi)ist迭代器失效, 這在vector是不成立的。

    2. 構(gòu)造函數(shù)

    • list<T> l;
    • list(beg, end)
    • list(n, elem)
    • list(const list &l)

    3. list賦值和交換

    函數(shù)原型

    • assign(beg, end)
    • assign(n, elem)
    • list& operator=(const list &l);
    • l.swap(l2)

    4. 大小操作

    函數(shù)原型:

    • size()
    • empty()
    • resize(num);
    • resize(num, elem)

    5. 插入和刪除操作

    函數(shù)原型:

    • push_back(elem)
    • pop_back()
    • push_front()
    • pop_front()
    • insert(iterator_pos, elem)
    • insert(iterator_pos, n, elem)
    • insert(iterator_pos, beg, end)
    • clear()
    • erase(beg, end)
    • erase(iterator_pos)
    • remove(elem) // 刪除容器中所有與elem值匹配的元素

    6. 數(shù)據(jù)存取

    函數(shù)原型:

    • front()
    • back()

    list本質(zhì)是鏈表,不是用連續(xù)線性空間存儲(chǔ)數(shù)據(jù),迭代器也不支持隨機(jī)訪問

    it++; it--; // 支持雙向 it = it + 1 // 錯(cuò)誤, 不支持隨機(jī)訪問

    7. 反轉(zhuǎn)和排序

    函數(shù)原型:

    • reverse() // 反轉(zhuǎn)列表
    • sort(); // 算法鏈表排序, 成員函數(shù),而不是全局函數(shù)
    list<int> l; // 所有不支持隨機(jī)訪問迭代器的容器,不可以使用標(biāo)準(zhǔn)算法排序 // 不支持隨機(jī)訪問迭代器的容器, 類內(nèi)部會(huì)提供對(duì)應(yīng)一些函數(shù) l.sort(); // 升序 // 降序 bool myCompare(int v1, int v2)return v1 > v2; l.sort(myCompare)

    8. 排序案例

    案例描述:將Person自定義數(shù)據(jù)類型進(jìn)行排序,Person中屬性有姓名、年齡、身高

    排序規(guī)則: 按照年齡進(jìn)行升序,如果年齡相同按照身高進(jìn)行降序

    void creatList(list<Person>& L) {Person p1("A", 12, 175);Person p2("B", 10, 175);Person p3("C", 17, 175);Person p4("D", 11, 175);Person p5("A", 12, 176);Person p6("A", 11, 185);L.push_back(p1);L.push_back(p2);L.push_back(p3);L.push_back(p4);L.push_back(p5);L.push_back(p6);for (list<Person>::iterator it = L.begin(); it != L.end(); it++) {cout << "姓名:" << it->m_Name << "年齡: " << it->m_Age << " 身高:" << it->m_Height << endl;} } bool comparePerson(Person& p1, Person& p2) {if (p1.m_Name == p2.m_Name) {if (p1.m_Age == p2.m_Age) {return p1.m_Height > p2.m_Height;}else {return p1.m_Age > p2.m_Age;}}return p1.m_Name > p2.m_Name; } int main() {list<Person> L;creatList(L);L.sort(comparePerson); // 指定排序規(guī)則for (list<Person>::iterator it = L.begin(); it != L.end(); it++) {cout << "姓名:" << it->m_Name << "年齡: " << it->m_Age << " 身高:" << it->m_Height << endl;}return 0; }

    總結(jié):使用自定義類型時(shí),要給sort指定排序規(guī)則

    3.8 set/multiset 容器 集合容器

    1. set/multiset基本概念

    簡(jiǎn)介:所有元素都會(huì)在插入時(shí) 自動(dòng)被排序

    本質(zhì)

    • set/multiset 屬于 關(guān)聯(lián)式容器, 底層結(jié)構(gòu)是用 二叉樹 實(shí)現(xiàn)

    setmultiset 的區(qū)別:

    • set不允許容器中有重復(fù)的元素
    • multiset允許容器中有重復(fù)的元素

    2. 構(gòu)造和賦值

    構(gòu)造

    • set<T> st;
    • set(const set &st)

    賦值

    • set& operator=(const set &st)

    插入

    • insert(elem)
    set<T> s; s.insert(1);

    3. set 大小和交換

    • size()
    • empty()
    • swap(st)

    4. 插入和刪除

    • insert(elem);
    • clear();
    • erase(pos)
    • erase(beg, end)
    • erase(elem)

    5. 查找和統(tǒng)計(jì)

    • 對(duì)set容器進(jìn)行查找數(shù)據(jù)以及統(tǒng)計(jì)數(shù)據(jù)

    函數(shù)原型

    • find(key) // 查找key,若存在返回該key的元素迭代器,若不存在,返回set.end()
    • count(key) // 統(tǒng)計(jì)key的個(gè)數(shù)
    s.find(1); s.count(1);

    6. set和multiset

    都包含在#include<set>頭文件中

    區(qū)別

    • set不可以插入重復(fù)數(shù)據(jù), 而multiset可以
    • set插入數(shù)據(jù)的同時(shí)會(huì) 返回插入結(jié)果,表示插入是否成功
    • multiset不會(huì)檢測(cè)數(shù)據(jù),因此可以插入重復(fù)數(shù)據(jù)
    set<int> s; pair<set<int>::iterator, bool> ret = s.insert(1); // 對(duì)組 ret.second;

    7. pair 對(duì)組創(chuàng)建

    • 成對(duì)出現(xiàn)的數(shù)據(jù),利用對(duì)組可以返回兩個(gè)數(shù)據(jù)

    兩種創(chuàng)建方式:

    • pair<type, type> p (value1, value2)
    • pair<type, type> p = make_pair(value1, value3)
    pair<string, int> p ("Tom", 20); // 獲取元素 pair.first; pair.second; pair<string, int> p = make_pair("Tom", 20);

    8. 改變set的排序規(guī)則

    利用 仿函數(shù),可以改變排序規(guī)則。

    仿函數(shù): 重載了函數(shù)調(diào)用運(yùn)算符(), 本質(zhì)上是一個(gè)類型

    // 內(nèi)置類型指定排序規(guī)則 class MyCompare { public:bool operator()(int v1, int v2) const { // 注意vs2019 重載()要加const return v1 > v2;} };int main() {// 指定排序規(guī)則 在插入數(shù)據(jù)之前set<int, MyCompare>s2;s2.insert(10);s2.insert(20);s2.insert(0);s2.insert(50);s2.insert(14);//printSet(s2);return 0; } // 自定義數(shù)據(jù)類型指定排序規(guī)則 class Person { public:Person(string name, int age) {this->m_Name = name;this->m_Age = age;}string m_Name;int m_Age; }; class MyCompare { public:bool operator()(Person p1, Person p2) { // 注意vs2019 重載()要加const return p1.m_Age > p2.m_Age;} };int main() {// 自定義數(shù)據(jù)類型 利用仿函數(shù)都會(huì)指定排序規(guī)則set<Person, MyCompare> s1;// 創(chuàng)建Person對(duì)象Person p1("劉備", 42);Person p2("司馬", 54);Person p3("曹操", 48);Person p4("孫權(quán)", 21);s1.insert(p1);s1.insert(p2);s1.insert(p3);s1.insert(p4);return 0; } // 該代碼g++編譯沒有問題, vs2019報(bào)錯(cuò)

    3.9 map/multimap 容器 高性能 高效率

    1. map的基本概念

    • map中所有元素都是pair
    • pair中第一個(gè)元素為key(鍵值),起到索引作用, 第二個(gè)元素為value(實(shí)值)
    • 所有元素都會(huì)根據(jù) 元素的鍵值 自動(dòng)排序

    本質(zhì):

    • map/multimap屬于關(guān)聯(lián)式容器,底層結(jié)構(gòu)是用二叉樹實(shí)現(xiàn)

    優(yōu)點(diǎn)

    • 可以根據(jù)key值快速找到value值

    map和multimap區(qū)別

    • map不允許容器有重復(fù)key值元素
    • multimap允許容器中有重復(fù)key值元素

    2. map構(gòu)造和賦值操作

    函數(shù)原型

    構(gòu)造

    • map<T1, T2> mp; // map默認(rèn)構(gòu)造函數(shù)
    • map(const map &mp);

    賦值

    • map& operator=(const map &mp)
    void printMap(const map<int, int>& m) {for (map<int, int>::const_iterator it = m.begin(); it != m.end(); it++) {cout << " 鍵:"<< it->first << "值:" << it->second << endl;;} }int main() {map<int, int> m; // map與set都是需要用set進(jìn)行插入數(shù)值,原因二叉樹結(jié)構(gòu)的關(guān)聯(lián)容器m.insert(pair<int, int>(1, 10)); // 使用匿名隊(duì)組printMap(m);map<int, int> m2(m);printMap(m);map<int, int>m3;m3 = m2;return 0; }

    3. map的容器大小 和交換

    函數(shù)原型:

    • size()
    • empty()
    • swap(mp)

    4. map的插入和刪除

    函數(shù)原型:

    • insert(elem)
    • clear()
    • erase(pos)
    • erase(pos, beg, end)
    • erase(key)
    // 插入方式 map<int, int> m; // 第一種 m.insert(pair<int, int>(1,10)); // 第二種 m.insert(make_pair(1,10)); // 第三種 m.insert(pair<int,int>::value_type(3,30)); // 第四種, 不建議插入, 可以利用key訪問value。 m[4] = 100; // 重載了[] // 第四種 容易出現(xiàn)的錯(cuò)誤 cout << m[5] << endl; // 會(huì)默認(rèn)生成一個(gè)key=5, value=0的元素

    5.map查找和統(tǒng)計(jì)

    函數(shù)原型

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

    6. map排序

    利用仿函數(shù),可以改變排序規(guī)則

    7. 案例

    4、函數(shù)對(duì)象

    4.1 概念:

    • 重載函數(shù)調(diào)用操作符()的類,其對(duì)象常稱為函數(shù)對(duì)象
    • 函數(shù)對(duì)象使用重載的() 時(shí),行為類似函數(shù)調(diào)用,也叫 仿函數(shù)

    本質(zhì):

    函數(shù)對(duì)象(仿函數(shù))是一個(gè)類,不是一個(gè)函數(shù)。

    4.2 函數(shù)對(duì)象使用

    特點(diǎn):

    • 函數(shù)對(duì)象在使用時(shí),可以像普通函數(shù)那樣調(diào)用,可有參數(shù),可有返回值
    • 函數(shù)對(duì)象超出普通函數(shù)的概念,函數(shù)對(duì)象可以有自己的狀態(tài)
    • 函數(shù)對(duì)象可以作為參數(shù)傳遞
    class MyAdd { public: MyAdd() {this->m_count = 0;}int operator()(int v1, int v2){ // 有參數(shù)有返回值this->m_count++;return v1 + v2;}int m_count; //自己的狀態(tài) 統(tǒng)計(jì)次數(shù) }; int main() {MyAdd myadd;int i = myadd(3, 5);cout << i << endl;cout << myadd.m_count << endl;return 0; }

    4.3 謂詞 Pred

    概念

    • 返回 bool類型 的仿函數(shù)稱為謂詞
    • 如果operator() 接受 一個(gè)參數(shù),那么叫做 一元謂詞
    • 如果operator() 接受兩個(gè)參數(shù),那么叫做 二元謂詞
    class GreaterFive{ // 一元謂詞 public:bool operator()(int val){return val>5;} };class Compare{ public:bool operator()(int v1, int v2){return v1 > v2} }int main(){vector<int> v;for(int i=0; i<10; i++){v.push_back(rand()%15);}// 1、使用一元謂詞// find_if 返回迭代器vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterFive()); // GreaterFive()匿名對(duì)象,()時(shí)調(diào)用了重載的()// 2、使用二元謂詞sort(v.begin(), v.end(), Compare());//注意這里傳入的是函數(shù)對(duì)象,set 是作為模板實(shí)現(xiàn)傳入return 0; }

    4.4 內(nèi)聯(lián)函數(shù)對(duì)象 functional

    概念: STL內(nèi)建了一些函數(shù)對(duì)象

    分類:

    • 算術(shù)仿函數(shù)
    • 關(guān)系仿函數(shù)
    • 邏輯仿函數(shù)

    用法:

    • 這些仿函數(shù)所產(chǎn)生的對(duì)象,用法和一般函數(shù)完全相同
    • 使用內(nèi)建函數(shù)對(duì)象,需要引入頭文件#include<functional>

    算術(shù)仿函數(shù) :

    • 實(shí)現(xiàn)四則運(yùn)算

    • 其中negate是一元運(yùn)算

    仿函數(shù)原型

    • template<class T> T plus<T> // 加法仿函數(shù) 注意只需要一個(gè)模板類型參數(shù),兩個(gè)會(huì)報(bào)錯(cuò)
    • template<class T> T minus<T> // 減法仿函數(shù)
    • template<class T> T multiplies<T> // 乘法仿函數(shù)
    • template<class T> T divides<T> // 除法仿函數(shù)
    • template<class T> T modules<T> // 取模仿函數(shù)
    • template<class T> T negate<T> // 取反仿函數(shù), 一元運(yùn)算
    #include<functional> negate<int> n; n(5); plus<int> p; // 二元謂詞也只傳入一個(gè)模板類型參數(shù) p(3,5);

    關(guān)系仿函數(shù)

    仿函數(shù)原型:

    • 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<class T> bool less<T>
    • template<class T> bool less_euqal<T>
    sort(beg, end, greater<int>())

    邏輯仿函數(shù)

    仿函數(shù)原型:

    • template<class T> bool logical_and<T>
    • template<class T> bool logical_or<T>
    • template<class T> bool logical_not<T>
    logical_not<bool> n;

    5、常用算法

    概述:

    • 算法主要由頭文件<algorithm> <functional> <numeric>

    • <algorithm>是STL頭文件中最大的一個(gè),范圍涉及到比較、交換、查找、遍歷操作、復(fù)制、修改等

    • <numeric> 體積很小,只包括幾個(gè)在序列上進(jìn)行簡(jiǎn)單數(shù)學(xué)運(yùn)算的模板函數(shù)

    • <functional> 定義了一些模板類,用以聲明函數(shù)對(duì)象

    5.1 常用的遍歷算法

    算法簡(jiǎn)介:

    • for_each() // 遍歷容器

    • transform // 搬運(yùn)容器到另一個(gè)容器

    函數(shù)原型:

    for_each(iterator beg, iterator end, _func) 第四個(gè)參數(shù)是普通函數(shù)或者仿函數(shù),提供了一種伴隨操作的方法

    // for_each(beg, end, 普通函數(shù)或者仿函數(shù)) #include<algorithm>void printVector(const int &val) {cout << val << " "; }class PrintVector { public:void operator()(int val) {cout << val << " ";} };int main(){vector<int> v;for (int i = 0; i < 10; i++) {v.push_back(rand()%21+10);}for_each(v.begin(), v.end(), printVector); // 注意這里是調(diào)用函數(shù) 因此只寫函數(shù)名代表函數(shù)地址cout << endl;for_each(v.begin(), v.end(), PrintVector()); // 注意這里是仿函數(shù)cout << endl;return 0; }

    函數(shù)原型:

    transform(iterator beg1, iterator end1, iterator beg2, _func) 第四個(gè)參數(shù)函數(shù)或者仿函數(shù)

    // transform class Transform{ public: int operator()(int val) {return val;} };int main(){vector<int> v;for (int i = 0; i < 10; i++) {v.push_back(rand()%21+10);}vector<int> target;target.resize(v.size()); // 目標(biāo)容器要提前開辟空間, 否則會(huì)報(bào)錯(cuò)transform(v.begin(), v.end(), target.begin(), Transform());return 0; }

    5.2 常用的查找算法

    • find // 查找元素
    • find_if // 按條件查找元素
    • adjacent_find // 查找相鄰的重復(fù)元素
    • binary_search // 二分查找
    • count // 統(tǒng)計(jì)元素個(gè)數(shù)
    • count_if // 按條件統(tǒng)計(jì)元素個(gè)數(shù)

    1. find

    函數(shù)原型:

    • find(iterator beg, iterator end, value) // 按條件查找元素,找到返回指定位置迭代器, 找不到返回結(jié)束迭代器位置
    // 查找自定義類型, 要在類內(nèi)重載==關(guān)系運(yùn)算符 class Person { public:Person(string name, int age) {this->m_Name = name;this->m_Age = age;}bool operator==(const Person& p) {if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) {return true;}else {return false;}}string m_Name;int m_Age; };int main(){vector<Person> v;Person p1("Tome", 13);Person p2("Tome", 3);Person p3("Tome", 213);Person p4("Tome", 113);v.push_back(p1);v.push_back(p2);v.push_back(p3);v.push_back(p4);vector<Person>::iterator it = find(v.begin(), v.end(), p2); // 要給自定義類型重載比較運(yùn)算return 0; }

    2. find_if

    函數(shù)原型:

    find_if(beg, end, _Pred)

    3. adjacent_find

    • 查找相鄰重復(fù)元素

    函數(shù)原型

    • adjacent_find(iterator beg, iterator end); // 返回相鄰元素的第一個(gè)元素的迭代器
    vector<int>:: iterator pos = adjacent_find(v.begin(), v.end());

    4. binary_search

    • 查找指定元素是否存在,返回值是bool類型,不是迭代器。效率較高
    • 必須在 有序 序列中使用,無序序列中不可用

    函數(shù)原型

    • bool binary_search(iterator beg, iterator end, value)

      返回true或者false

    5. count

    統(tǒng)計(jì)元素個(gè)數(shù)

    函數(shù)原型:

    • count(iterator beg, iterator end, value)

      返回統(tǒng)計(jì)元素出現(xiàn)的次數(shù)

    6. count_if

    按條件統(tǒng)計(jì)元素個(gè)數(shù)

    函數(shù)原型:

    • count(iterator beg, iterator end, _Pred)

      返回統(tǒng)計(jì)元素出現(xiàn)的次數(shù)

    5.3 常用的排序算法

    算法簡(jiǎn)介

    • sort() // 對(duì)容器內(nèi)元素進(jìn)行排序
    • random_shuffle // 洗牌, 指定范圍內(nèi)的元素隨機(jī)調(diào)整次序
    • merge // 容器元素合并,并存儲(chǔ)到另一個(gè)容器中
    • reverse // 反轉(zhuǎn)指定范圍的元素

    1. sort

    對(duì)容器內(nèi)元素進(jìn)行排序

    函數(shù)原型

    • sort(iterator beg, iterator end, _Pred)

    2. random_shuffle

    洗牌 指定范圍內(nèi)元素隨機(jī)排序

    函數(shù)原型

    • random_shuffle(iterator beg, iterator end)

      可以使用隨機(jī)種子srand((unsigned int)time(nullptr));

    3. merge

    兩個(gè)有序序列合并成一個(gè)有序序列,并存儲(chǔ)到另一個(gè)容器,

    函數(shù)原型

    • merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest_beg)

    4. reverse

    對(duì)容器內(nèi)元素進(jìn)行反轉(zhuǎn)

    函數(shù)原型

    • reverse(iterator beg, iterator end);

      反轉(zhuǎn)指定范圍的元素

    reverse(v.begin(), v.end()); // 可以用在字符串反轉(zhuǎn)中

    5.4 常用的拷貝和替換算法

    算法簡(jiǎn)介:

    • copy //容器內(nèi)指定范圍的元素拷貝到另一個(gè)容器
    • replace ://容器內(nèi)指定舊元素,替換為新元素
    • replace_if//容器內(nèi)指定范圍的舊元素,滿足條件的替換為新元素
    • swap // 互換兩個(gè)容器的元素

    1. copy 可以用賦值=來替代

    函數(shù)原型

    • copy(iterator beg, iterator end, iterator dest)

      copy(v1.begin(), v1.end(), v2.begin()); // 目標(biāo)容器要提前開辟空間

    2. replace

    函數(shù)原型

    • replace(iterator beg, iterator end, oldvalue, newvalue)
    replace(v.begin(), v.end(), 1, 2);

    3. replace_if

    按條件替換,區(qū)間內(nèi)滿足條件的替換為新元素

    函數(shù)原型

    • replace_if(iterator beg, iterator end, _Pred, newvalue)

    利用仿函數(shù)可以靈活篩選滿足條件

    4. swap

    互換兩個(gè)相同類型容器中的元素

    函數(shù)原型

    • swap(container c1, container c2);

    5.5 常用的算術(shù)生成算法

    頭文件#include <numeric>

    算法簡(jiǎn)介:

    • acccumulate // 計(jì)算容器元素累計(jì)和
    • fill // 向容器中添加元素

    1. accumulate

    計(jì)算區(qū)間內(nèi)元素累計(jì)總和

    函數(shù)原型

    • accumulate(iterator beg, iterator end, value)

      value : 起始的累加值

    int total = accumulate(v.begin(), v.end(), 0);

    2. fill

    向容器中填充指定的元素

    函數(shù)原型

    • fill(iterator beg, iterator end, value)

      value 填充值

    5.6 常用的集合算法

    算法簡(jiǎn)介:

    • set_intersection // 求兩個(gè)容器的交集
    • set_union // 求兩個(gè)容器的并集
    • set_difference //求兩個(gè)容器的差集

    1. set_intersection

    求兩個(gè)容器的交集

    • set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)

      交集放在目標(biāo)容器中,目標(biāo)容器需要提前開辟空間,因?yàn)槭墙患∽钚〉?/p>

      注意,該算法會(huì)返回交集末尾的迭代器。

    dest.resize(min(v1.size,v2.size())) vector<int>::iterator iEnd = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), dest.begin()); // 輸出 要用iEnd來作為dest的結(jié)束迭代器

    2. set_union

    求兩個(gè)容器的并集, 要求兩個(gè)集合必須是有序序列

    • set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)

      并集放在目標(biāo)容器中,目標(biāo)容器需要提前開辟空間,因?yàn)槭遣⒓?#xff0c;所以取兩個(gè)容器之和

      同樣要注意,要利用返回的迭代器來作為并集末尾的迭代器

    3. set_difference

    求兩個(gè)集合的差集, 兩個(gè)集合必須是有序序列

    理解: v1, v2 v1中 不屬于v1,v2 交集 的元素; v2中 不屬于v1,v2 交集 的元素; 因此注意前后順序

    • set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)

      交集放在目標(biāo)容器中,目標(biāo)容器需要提前開辟空間,取兩個(gè)中最大的容器大小(個(gè)人感覺取前面的容器大小就行)

      同樣要注意,要利用返回的迭代器來作為差集末尾的迭代器

    枚舉類

    C++ 其他知識(shí)點(diǎn)

    1、cin

    注意類型匹配

    int a; cin >> a; // 如果鍵盤輸入的是字母, 則a=0。

    2、隨機(jī)數(shù)

    // 隨機(jī)數(shù)種子 #include <ctime> srand((unsigned int)time(NULL)); rand()

    3、system

    system("pause"); // 請(qǐng)按任意鍵繼續(xù) system("cls"); // 清屏操作

    4、彩色字體輸出

    cout << "\033[1;33m" << "輸出內(nèi)容" << "\033[0m" << endl;

    5、C++編譯

    使用g++命令編譯c++文件而不是gcc

    總結(jié)

    以上是生活随笔為你收集整理的C++笔记汇总的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    日本成熟视频免费视频 | 蜜臀av无码人妻精品 | 色诱久久久久综合网ywww | 麻豆av传媒蜜桃天美传媒 | 99久久久国产精品无码免费 | 成年美女黄网站色大免费视频 | 亚洲男人av香蕉爽爽爽爽 | 久精品国产欧美亚洲色aⅴ大片 | 色窝窝无码一区二区三区色欲 | 国产在线无码精品电影网 | 国产免费观看黄av片 | 亚洲成av人在线观看网址 | a在线观看免费网站大全 | 正在播放老肥熟妇露脸 | 久久久婷婷五月亚洲97号色 | 国产午夜精品一区二区三区嫩草 | 国产精品亚洲а∨无码播放麻豆 | 丰满少妇女裸体bbw | 少妇久久久久久人妻无码 | 亚洲精品一区三区三区在线观看 | 久久97精品久久久久久久不卡 | 国产一精品一av一免费 | 亚洲国产精品成人久久蜜臀 | 亚洲综合在线一区二区三区 | 亚洲乱码国产乱码精品精 | 久久久久亚洲精品中文字幕 | av在线亚洲欧洲日产一区二区 | 亚洲 激情 小说 另类 欧美 | 人人妻人人澡人人爽人人精品 | 高潮毛片无遮挡高清免费视频 | 国产精品igao视频网 | 7777奇米四色成人眼影 | 人妻尝试又大又粗久久 | 日本饥渴人妻欲求不满 | 中文亚洲成a人片在线观看 | 牛和人交xxxx欧美 | 国内精品人妻无码久久久影院 | 国产av久久久久精东av | 在线a亚洲视频播放在线观看 | 欧美丰满老熟妇xxxxx性 | 欧美亚洲日韩国产人成在线播放 | 国产成人人人97超碰超爽8 | 99视频精品全部免费免费观看 | 成人无码精品一区二区三区 | 色欲综合久久中文字幕网 | 亚洲一区二区三区偷拍女厕 | 欧美日韩亚洲国产精品 | 夜夜夜高潮夜夜爽夜夜爰爰 | 又大又硬又黄的免费视频 | 国产在线精品一区二区三区直播 | 综合人妻久久一区二区精品 | 国产精品高潮呻吟av久久 | 亚洲成av人影院在线观看 | 国产精品爱久久久久久久 | 国产成人亚洲综合无码 | 亚洲无人区一区二区三区 | 免费网站看v片在线18禁无码 | 精品无码国产一区二区三区av | 天天拍夜夜添久久精品 | 波多野结衣av在线观看 | 久久国产自偷自偷免费一区调 | 亚洲国产高清在线观看视频 | 激情内射亚州一区二区三区爱妻 | 国产莉萝无码av在线播放 | 午夜精品一区二区三区的区别 | 荫蒂被男人添的好舒服爽免费视频 | 亚洲日本在线电影 | 亚洲人交乣女bbw | 欧美老熟妇乱xxxxx | 国产亚洲欧美在线专区 | 国产无套粉嫩白浆在线 | 蜜桃无码一区二区三区 | 午夜肉伦伦影院 | 97人妻精品一区二区三区 | 久久99精品久久久久久动态图 | 亚洲の无码国产の无码影院 | v一区无码内射国产 | 久久人人爽人人人人片 | 我要看www免费看插插视频 | 国产内射爽爽大片视频社区在线 | 无码一区二区三区在线观看 | 欧洲vodafone精品性 | 人人妻人人澡人人爽欧美一区 | 国语自产偷拍精品视频偷 | 亚洲狠狠婷婷综合久久 | 国产香蕉尹人综合在线观看 | 精品人妻中文字幕有码在线 | 免费看少妇作爱视频 | 国产偷国产偷精品高清尤物 | 国产亚洲精品久久久久久久 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 性史性农村dvd毛片 | 久久精品国产99精品亚洲 | 成人影院yy111111在线观看 | 玩弄中年熟妇正在播放 | 亚洲熟妇色xxxxx欧美老妇 | 精品水蜜桃久久久久久久 | 国产成人无码一二三区视频 | 久久精品成人欧美大片 | 久久综合激激的五月天 | 精品偷自拍另类在线观看 | 丰满妇女强制高潮18xxxx | 国产精品久久久久久久影院 | 男女超爽视频免费播放 | 国产精品人人妻人人爽 | 无码一区二区三区在线观看 | 国产精品人妻一区二区三区四 | 国产香蕉97碰碰久久人人 | 在线观看国产午夜福利片 | 丰满少妇弄高潮了www | 国内丰满熟女出轨videos | 亚洲一区二区三区 | 亚洲综合在线一区二区三区 | 中文精品久久久久人妻不卡 | 日韩在线不卡免费视频一区 | 国产成人午夜福利在线播放 | 久久熟妇人妻午夜寂寞影院 | 无套内射视频囯产 | 国产人成高清在线视频99最全资源 | 亚无码乱人伦一区二区 | 波多野结衣一区二区三区av免费 | 99国产欧美久久久精品 | 国产精品国产自线拍免费软件 | 曰韩少妇内射免费播放 | 亚洲春色在线视频 | 蜜臀av在线观看 在线欧美精品一区二区三区 | 亚洲人成影院在线无码按摩店 | 日本精品人妻无码77777 天堂一区人妻无码 | 国产美女精品一区二区三区 | 少妇性俱乐部纵欲狂欢电影 | 国产成人av免费观看 | 亚洲精品国产第一综合99久久 | 免费观看激色视频网站 | 国产精品亚洲lv粉色 | 久久精品99久久香蕉国产色戒 | 成人免费视频视频在线观看 免费 | 97精品国产97久久久久久免费 | 久久婷婷五月综合色国产香蕉 | 97夜夜澡人人爽人人喊中国片 | 国产国语老龄妇女a片 | 国产真人无遮挡作爱免费视频 | av无码不卡在线观看免费 | 日本精品人妻无码77777 天堂一区人妻无码 | 老熟妇乱子伦牲交视频 | 亚洲国精产品一二二线 | 真人与拘做受免费视频 | 九九在线中文字幕无码 | 麻豆人妻少妇精品无码专区 | 高清不卡一区二区三区 | 免费观看的无遮挡av | 人妻天天爽夜夜爽一区二区 | 国产成人久久精品流白浆 | 少妇无码av无码专区在线观看 | 少妇性荡欲午夜性开放视频剧场 | 在线天堂新版最新版在线8 | 99麻豆久久久国产精品免费 | 欧美日本免费一区二区三区 | 国产人妻久久精品二区三区老狼 | 欧美熟妇另类久久久久久多毛 | 伊人久久大香线蕉亚洲 | 精品国产乱码久久久久乱码 | 呦交小u女精品视频 | 婷婷六月久久综合丁香 | 欧美性猛交内射兽交老熟妇 | 日本熟妇浓毛 | 天天拍夜夜添久久精品大 | 欧美阿v高清资源不卡在线播放 | 正在播放老肥熟妇露脸 | 亚洲一区二区三区偷拍女厕 | 人妻无码久久精品人妻 | 无码播放一区二区三区 | 亚洲精品久久久久avwww潮水 | 国产成人午夜福利在线播放 | 国产情侣作爱视频免费观看 | 老子影院午夜精品无码 | 亚洲人成网站免费播放 | 少妇无套内谢久久久久 | 在线观看国产一区二区三区 | 俄罗斯老熟妇色xxxx | 高潮毛片无遮挡高清免费 | 精品国偷自产在线 | 免费无码的av片在线观看 | 欧美老人巨大xxxx做受 | 欧美日本精品一区二区三区 | 国内精品久久久久久中文字幕 | 又粗又大又硬又长又爽 | 1000部夫妻午夜免费 | 国产精品国产自线拍免费软件 | 午夜丰满少妇性开放视频 | 成人欧美一区二区三区黑人免费 | 福利一区二区三区视频在线观看 | 九九综合va免费看 | 色欲久久久天天天综合网精品 | 人妻天天爽夜夜爽一区二区 | 狠狠色欧美亚洲狠狠色www | 国产精品美女久久久 | 丰满少妇女裸体bbw | 麻豆精品国产精华精华液好用吗 | 精品厕所偷拍各类美女tp嘘嘘 | 欧美成人免费全部网站 | 亚洲一区二区三区 | 无码人妻久久一区二区三区不卡 | 好屌草这里只有精品 | 成人精品一区二区三区中文字幕 | 亚洲一区二区三区偷拍女厕 | 捆绑白丝粉色jk震动捧喷白浆 | 伊人久久大香线蕉亚洲 | 在线播放无码字幕亚洲 | 久久国语露脸国产精品电影 | 女人被男人爽到呻吟的视频 | 午夜福利试看120秒体验区 | 国产亚洲精品久久久久久国模美 | 亚洲色在线无码国产精品不卡 | 露脸叫床粗话东北少妇 | 亚洲欧洲中文日韩av乱码 | 亚洲欧美日韩成人高清在线一区 | 成年女人永久免费看片 | 国产精品高潮呻吟av久久 | 女人被爽到呻吟gif动态图视看 | 精品国产乱码久久久久乱码 | 中国女人内谢69xxxx | 日本一区二区三区免费高清 | 久久午夜夜伦鲁鲁片无码免费 | 人人妻在人人 | 国产成人午夜福利在线播放 | 国产乱码精品一品二品 | 国产特级毛片aaaaaa高潮流水 | av人摸人人人澡人人超碰下载 | 国产麻豆精品一区二区三区v视界 | a在线观看免费网站大全 | 久久精品国产一区二区三区肥胖 | 人人澡人人妻人人爽人人蜜桃 | 久久99精品国产.久久久久 | 一个人看的视频www在线 | 欧美黑人性暴力猛交喷水 | 日本丰满熟妇videos | 少妇性荡欲午夜性开放视频剧场 | 久久午夜无码鲁丝片秋霞 | 在线播放无码字幕亚洲 | 久久久久成人精品免费播放动漫 | 亚洲精品国产精品乱码视色 | 免费观看的无遮挡av | аⅴ资源天堂资源库在线 | 欧美野外疯狂做受xxxx高潮 | 在线 国产 欧美 亚洲 天堂 | 夜夜夜高潮夜夜爽夜夜爰爰 | 无码纯肉视频在线观看 | 性色av无码免费一区二区三区 | 波多野结衣av在线观看 | 精品欧洲av无码一区二区三区 | 精品国偷自产在线视频 | 清纯唯美经典一区二区 | 午夜精品一区二区三区的区别 | 免费无码的av片在线观看 | 欧美丰满少妇xxxx性 | 在线成人www免费观看视频 | 99久久无码一区人妻 | 国产偷国产偷精品高清尤物 | 亚洲第一网站男人都懂 | 国产后入清纯学生妹 | 久久精品中文字幕大胸 | 亚洲狠狠婷婷综合久久 | 蜜桃av抽搐高潮一区二区 | 国产女主播喷水视频在线观看 | 色婷婷综合中文久久一本 | 亚洲国产av精品一区二区蜜芽 | 国产网红无码精品视频 | 大地资源网第二页免费观看 | 7777奇米四色成人眼影 | 一本一道久久综合久久 | 色五月丁香五月综合五月 | 桃花色综合影院 | 欧洲极品少妇 | ass日本丰满熟妇pics | 亚洲国产精品无码一区二区三区 | 美女扒开屁股让男人桶 | 欧美老妇交乱视频在线观看 | 国内综合精品午夜久久资源 | 夜夜夜高潮夜夜爽夜夜爰爰 | 老熟女乱子伦 | 人人爽人人澡人人高潮 | 国产精品对白交换视频 | 欧美自拍另类欧美综合图片区 | 日韩精品a片一区二区三区妖精 | 999久久久国产精品消防器材 | 日本xxxx色视频在线观看免费 | 日本xxxx色视频在线观看免费 | 青草青草久热国产精品 | 国产精品高潮呻吟av久久 | 久久精品视频在线看15 | 内射巨臀欧美在线视频 | 红桃av一区二区三区在线无码av | 牲欲强的熟妇农村老妇女 | 欧美成人家庭影院 | 日日天干夜夜狠狠爱 | 欧洲美熟女乱又伦 | 日韩人妻无码一区二区三区久久99 | 欧美国产日韩亚洲中文 | 一区二区三区高清视频一 | 大地资源网第二页免费观看 | 婷婷丁香五月天综合东京热 | 成人无码影片精品久久久 | 2019nv天堂香蕉在线观看 | 日本护士xxxxhd少妇 | 大地资源网第二页免费观看 | 在教室伦流澡到高潮hnp视频 | 亚洲一区二区三区香蕉 | 男人和女人高潮免费网站 | 欧美成人高清在线播放 | 亚洲精品成人福利网站 | 18精品久久久无码午夜福利 | 久久aⅴ免费观看 | 欧美熟妇另类久久久久久多毛 | 亚洲国产成人av在线观看 | 巨爆乳无码视频在线观看 | 国产亚洲精品久久久久久 | 久久亚洲精品成人无码 | 久久精品成人欧美大片 | 久久天天躁狠狠躁夜夜免费观看 | 妺妺窝人体色www在线小说 | 少妇人妻偷人精品无码视频 | 成人免费视频视频在线观看 免费 | 一本大道久久东京热无码av | 日本精品久久久久中文字幕 | 97无码免费人妻超级碰碰夜夜 | 男女猛烈xx00免费视频试看 | 亚洲精品欧美二区三区中文字幕 | 精品少妇爆乳无码av无码专区 | 久久精品女人天堂av免费观看 | 1000部夫妻午夜免费 | 丰满少妇女裸体bbw | 中国女人内谢69xxxxxa片 | 欧美真人作爱免费视频 | 久久午夜无码鲁丝片午夜精品 | 久久久久久久久蜜桃 | 亚洲熟妇色xxxxx亚洲 | 一本精品99久久精品77 | 精品无码国产自产拍在线观看蜜 | 国产办公室秘书无码精品99 | 大乳丰满人妻中文字幕日本 | 无码吃奶揉捏奶头高潮视频 | 亚洲 欧美 激情 小说 另类 | 亚洲理论电影在线观看 | 人妻与老人中文字幕 | 欧美精品免费观看二区 | 爽爽影院免费观看 | 亚洲 另类 在线 欧美 制服 | 日韩视频 中文字幕 视频一区 | 中文字幕日韩精品一区二区三区 | av香港经典三级级 在线 | av香港经典三级级 在线 | 无码播放一区二区三区 | 亚洲天堂2017无码 | 成人无码精品一区二区三区 | 欧美高清在线精品一区 | 天天综合网天天综合色 | 在线视频网站www色 | 2020久久香蕉国产线看观看 | 最新国产麻豆aⅴ精品无码 | 欧美老熟妇乱xxxxx | 亚洲精品久久久久久一区二区 | 久久久久亚洲精品男人的天堂 | 欧美日韩在线亚洲综合国产人 | 暴力强奷在线播放无码 | 欧美熟妇另类久久久久久多毛 | 欧美 日韩 人妻 高清 中文 | 亚洲日本一区二区三区在线 | 中文字幕人妻无码一夲道 | 久久国产精品_国产精品 | 色综合久久久无码中文字幕 | 国内精品久久久久久中文字幕 | 呦交小u女精品视频 | 曰韩无码二三区中文字幕 | 色婷婷综合中文久久一本 | 国产另类ts人妖一区二区 | 色综合久久中文娱乐网 | 亚洲国精产品一二二线 | 少妇太爽了在线观看 | 中文字幕久久久久人妻 | 久久久久久久人妻无码中文字幕爆 | 一个人看的视频www在线 | 性欧美大战久久久久久久 | 国产精品久久久久影院嫩草 | 亚洲国产精品久久久久久 | 一本久道高清无码视频 | 欧美人与禽zoz0性伦交 | 美女扒开屁股让男人桶 | www一区二区www免费 | 波多野结衣 黑人 | 成人试看120秒体验区 | 国产成人精品无码播放 | 丁香啪啪综合成人亚洲 | 黑人粗大猛烈进出高潮视频 | 欧美一区二区三区 | 国产欧美精品一区二区三区 | 日韩精品无码一本二本三本色 | 欧美性色19p | 国产成人av免费观看 | 无码人妻久久一区二区三区不卡 | 国产精品久久久久影院嫩草 | 国产超级va在线观看视频 | 国产高潮视频在线观看 | 人人妻人人藻人人爽欧美一区 | 清纯唯美经典一区二区 | 亚洲欧美日韩综合久久久 | 国产色xx群视频射精 | 波多野结衣aⅴ在线 | 亚拍精品一区二区三区探花 | 少妇性俱乐部纵欲狂欢电影 | 欧美丰满少妇xxxx性 | 精品国产一区二区三区av 性色 | 午夜不卡av免费 一本久久a久久精品vr综合 | 欧美日韩在线亚洲综合国产人 | 国产麻豆精品一区二区三区v视界 | 色欲人妻aaaaaaa无码 | 少妇邻居内射在线 | 欧美日韩久久久精品a片 | 亚洲综合另类小说色区 | 日日噜噜噜噜夜夜爽亚洲精品 | 国产精品毛片一区二区 | 丰满少妇弄高潮了www | 国产成人无码区免费内射一片色欲 | 亚洲の无码国产の无码影院 | а天堂中文在线官网 | 扒开双腿吃奶呻吟做受视频 | 丰满少妇熟乱xxxxx视频 | 美女黄网站人色视频免费国产 | 国产精品亚洲一区二区三区喷水 | 欧美人与善在线com | 激情综合激情五月俺也去 | 免费无码的av片在线观看 | 在教室伦流澡到高潮hnp视频 | 图片小说视频一区二区 | 无人区乱码一区二区三区 | 中文字幕人成乱码熟女app | 青青青手机频在线观看 | 亚洲狠狠婷婷综合久久 | 天堂久久天堂av色综合 | 美女黄网站人色视频免费国产 | 国产免费久久久久久无码 | 国产精品免费大片 | 人妻少妇被猛烈进入中文字幕 | 亚洲色偷偷偷综合网 | 亚洲精品一区二区三区在线观看 | 美女张开腿让人桶 | 国产精品va在线观看无码 | 亚洲娇小与黑人巨大交 | 亚洲精品欧美二区三区中文字幕 | 麻豆蜜桃av蜜臀av色欲av | 377p欧洲日本亚洲大胆 | 亚洲码国产精品高潮在线 | 欧洲精品码一区二区三区免费看 | 动漫av一区二区在线观看 | 麻豆果冻传媒2021精品传媒一区下载 | 在线观看免费人成视频 | 国产三级精品三级男人的天堂 | 国产无套内射久久久国产 | 久久综合激激的五月天 | 中文字幕人成乱码熟女app | 日本乱偷人妻中文字幕 | 久久99精品久久久久婷婷 | 人人爽人人澡人人高潮 | 偷窥日本少妇撒尿chinese | 伊人久久大香线蕉午夜 | 乱人伦中文视频在线观看 | 无码精品国产va在线观看dvd | 巨爆乳无码视频在线观看 | 97无码免费人妻超级碰碰夜夜 | 97久久国产亚洲精品超碰热 | 四虎永久在线精品免费网址 | 欧美激情综合亚洲一二区 | 女人高潮内射99精品 | 亚洲成a人片在线观看无码 | 国产精品欧美成人 | 真人与拘做受免费视频一 | 国产特级毛片aaaaaa高潮流水 | 在教室伦流澡到高潮hnp视频 | 丰满岳乱妇在线观看中字无码 | 亚洲一区二区三区在线观看网站 | 给我免费的视频在线观看 | 国产午夜亚洲精品不卡 | 亚洲小说春色综合另类 | 一个人看的视频www在线 | 亚洲综合无码一区二区三区 | 精品厕所偷拍各类美女tp嘘嘘 | 鲁大师影院在线观看 | 无码人妻精品一区二区三区下载 | 无码人妻出轨黑人中文字幕 | а√天堂www在线天堂小说 | 高中生自慰www网站 | 男女下面进入的视频免费午夜 | 欧洲极品少妇 | 成人无码精品一区二区三区 | 国产精品多人p群无码 | 四虎国产精品一区二区 | 宝宝好涨水快流出来免费视频 | 美女扒开屁股让男人桶 | 国产成人无码午夜视频在线观看 | 日本一区二区三区免费高清 | 99精品久久毛片a片 | 亚洲国产精品久久久天堂 | 色窝窝无码一区二区三区色欲 | 国产亚洲美女精品久久久2020 | 国产精品久久久久9999小说 | 亚洲一区av无码专区在线观看 | 亚洲国产欧美国产综合一区 | 久久综合网欧美色妞网 | 国产69精品久久久久app下载 | 亚洲综合伊人久久大杳蕉 | 国产精品无码久久av | 自拍偷自拍亚洲精品10p | 亚洲精品无码人妻无码 | 亚洲国产高清在线观看视频 | 日韩精品一区二区av在线 | 欧美性猛交内射兽交老熟妇 | 中文字幕精品av一区二区五区 | 国产精品99爱免费视频 | 国产特级毛片aaaaaa高潮流水 | 亚洲熟女一区二区三区 | 国产va免费精品观看 | 亚洲娇小与黑人巨大交 | 国产人妻大战黑人第1集 | 亚洲の无码国产の无码步美 | 夜夜影院未满十八勿进 | 国产精品成人av在线观看 | 少妇性荡欲午夜性开放视频剧场 | 亚洲天堂2017无码 | 色婷婷久久一区二区三区麻豆 | 成人欧美一区二区三区黑人免费 | 国产人妖乱国产精品人妖 | 精品久久综合1区2区3区激情 | 在线精品国产一区二区三区 | 国产午夜亚洲精品不卡 | 国产又粗又硬又大爽黄老大爷视 | 国内丰满熟女出轨videos | 丰满人妻一区二区三区免费视频 | 国产精品怡红院永久免费 | 中文无码伦av中文字幕 | 国产亚洲视频中文字幕97精品 | 天天做天天爱天天爽综合网 | 久久久亚洲欧洲日产国码αv | 伊人久久大香线焦av综合影院 | 亚洲精品一区二区三区在线观看 | 久久国产精品_国产精品 | 噜噜噜亚洲色成人网站 | 最新国产乱人伦偷精品免费网站 | 暴力强奷在线播放无码 | 欧洲欧美人成视频在线 | 中文字幕日产无线码一区 | 小sao货水好多真紧h无码视频 | 无码av中文字幕免费放 | 中文字幕无码免费久久9一区9 | 伦伦影院午夜理论片 | 99精品视频在线观看免费 | 亚洲高清偷拍一区二区三区 | 久在线观看福利视频 | 给我免费的视频在线观看 | 丰满肥臀大屁股熟妇激情视频 | 奇米影视7777久久精品人人爽 | 日本欧美一区二区三区乱码 | 欧美性生交活xxxxxdddd | 在线亚洲高清揄拍自拍一品区 | 亚洲中文无码av永久不收费 | 荡女精品导航 | 亚洲人成影院在线无码按摩店 | 骚片av蜜桃精品一区 | 亚洲欧洲日本无在线码 | 麻豆果冻传媒2021精品传媒一区下载 | 欧美国产日韩亚洲中文 | 成人亚洲精品久久久久软件 | 亚洲狠狠色丁香婷婷综合 | 1000部夫妻午夜免费 | 国产熟女一区二区三区四区五区 | 国产另类ts人妖一区二区 | 久久精品人妻少妇一区二区三区 | 中文字幕色婷婷在线视频 | 国产欧美精品一区二区三区 | 午夜熟女插插xx免费视频 | 欧美日本免费一区二区三区 | 国产亚洲精品精品国产亚洲综合 | 免费观看又污又黄的网站 | 亚洲人成网站色7799 | 人妻少妇被猛烈进入中文字幕 | 国产激情艳情在线看视频 | 中文字幕无码免费久久99 | 女人被男人爽到呻吟的视频 | 一本色道婷婷久久欧美 | 欧美国产日韩亚洲中文 | 无码毛片视频一区二区本码 | 日本一区二区更新不卡 | 午夜精品一区二区三区的区别 | 一区二区三区乱码在线 | 欧洲 | 中文字幕日韩精品一区二区三区 | 人妻少妇被猛烈进入中文字幕 | 午夜精品久久久久久久 | 露脸叫床粗话东北少妇 | 国产成人综合美国十次 | 骚片av蜜桃精品一区 | 欧洲精品码一区二区三区免费看 | 久久国产精品萌白酱免费 | 99久久精品日本一区二区免费 | 国产精品国产自线拍免费软件 | 白嫩日本少妇做爰 | 中文字幕人妻无码一夲道 | 日本xxxx色视频在线观看免费 | 成人无码视频在线观看网站 | 亚洲毛片av日韩av无码 | 国产午夜亚洲精品不卡下载 | 国产卡一卡二卡三 | 国产人妻精品一区二区三区 | 人妻与老人中文字幕 | 亚洲小说春色综合另类 | 88国产精品欧美一区二区三区 | 九九综合va免费看 | 国产高清不卡无码视频 | 日韩欧美群交p片內射中文 | 国产精品理论片在线观看 | а√天堂www在线天堂小说 | 久激情内射婷内射蜜桃人妖 | 精品国产一区二区三区四区在线看 | 欧美性猛交xxxx富婆 | 天堂亚洲2017在线观看 | 高潮毛片无遮挡高清免费视频 | 婷婷综合久久中文字幕蜜桃三电影 | av无码久久久久不卡免费网站 | 成年美女黄网站色大免费视频 | 亚洲va中文字幕无码久久不卡 | 国产av人人夜夜澡人人爽麻豆 | 久久综合狠狠综合久久综合88 | 久久久久av无码免费网 | 蜜臀aⅴ国产精品久久久国产老师 | 国产亚洲精品久久久久久国模美 | 老熟女重囗味hdxx69 | 午夜肉伦伦影院 | 伦伦影院午夜理论片 | 国产午夜精品一区二区三区嫩草 | 国产内射老熟女aaaa | 婷婷综合久久中文字幕蜜桃三电影 | 成人一区二区免费视频 | 国产va免费精品观看 | 天堂亚洲2017在线观看 | 性欧美大战久久久久久久 | 欧美精品国产综合久久 | 亚洲一区二区三区含羞草 | 午夜丰满少妇性开放视频 | 国产精品.xx视频.xxtv | 亚洲爆乳无码专区 | 久久国产精品_国产精品 | 亚洲精品久久久久久一区二区 | 亚洲小说图区综合在线 | 国产小呦泬泬99精品 | 久久久中文字幕日本无吗 | 最近免费中文字幕中文高清百度 | 亚洲经典千人经典日产 | 亚洲va欧美va天堂v国产综合 | 亚洲熟妇自偷自拍另类 | 奇米影视7777久久精品人人爽 | 久久久精品人妻久久影视 | 亚洲综合在线一区二区三区 | 亚洲综合无码一区二区三区 | 97久久超碰中文字幕 | 国产极品美女高潮无套在线观看 | 妺妺窝人体色www婷婷 | 精品偷自拍另类在线观看 | 在线а√天堂中文官网 | 精品国产aⅴ无码一区二区 | 精品久久久久久亚洲精品 | 婷婷五月综合缴情在线视频 | 人人爽人人爽人人片av亚洲 | 2020最新国产自产精品 | 中文字幕乱码亚洲无线三区 | 丰满人妻一区二区三区免费视频 | 免费国产黄网站在线观看 | 国产午夜福利100集发布 | 久久久久人妻一区精品色欧美 | 人人澡人摸人人添 | 国产偷抇久久精品a片69 | 国产精品亚洲lv粉色 | 色偷偷人人澡人人爽人人模 | 真人与拘做受免费视频一 | 亚洲 日韩 欧美 成人 在线观看 | 蜜桃av抽搐高潮一区二区 | 又大又硬又黄的免费视频 | 日日碰狠狠丁香久燥 | 丝袜人妻一区二区三区 | yw尤物av无码国产在线观看 | 日韩成人一区二区三区在线观看 | 无码人妻精品一区二区三区下载 | 东京无码熟妇人妻av在线网址 | 思思久久99热只有频精品66 | 999久久久国产精品消防器材 | 2020久久香蕉国产线看观看 | 美女扒开屁股让男人桶 | 欧美喷潮久久久xxxxx | 亚洲色欲久久久综合网东京热 | 特级做a爰片毛片免费69 | 国产精品无码mv在线观看 | 亚洲自偷自偷在线制服 | 国产精品丝袜黑色高跟鞋 | 内射欧美老妇wbb | 久久久国产精品无码免费专区 | 图片区 小说区 区 亚洲五月 | 欧美人与善在线com | 国产人妻久久精品二区三区老狼 | 日日天日日夜日日摸 | 国产av一区二区精品久久凹凸 | 久久久久久久女国产乱让韩 | 久久伊人色av天堂九九小黄鸭 | 中国大陆精品视频xxxx | 欧美变态另类xxxx | 激情综合激情五月俺也去 | 精品一区二区三区波多野结衣 | 国产精华av午夜在线观看 | 夜夜夜高潮夜夜爽夜夜爰爰 | 国产真实乱对白精彩久久 | 国产精品99爱免费视频 | 国产人妻精品一区二区三区 | 捆绑白丝粉色jk震动捧喷白浆 | www国产精品内射老师 | 久久精品国产一区二区三区肥胖 | 亚洲精品一区二区三区大桥未久 | 免费观看黄网站 | 少妇性荡欲午夜性开放视频剧场 | 亚欧洲精品在线视频免费观看 | 粉嫩少妇内射浓精videos | 国产精品第一国产精品 | 扒开双腿吃奶呻吟做受视频 | 玩弄中年熟妇正在播放 | 国产精品久久久久无码av色戒 | 国产人妻人伦精品1国产丝袜 | 亚洲爆乳无码专区 | 亚洲s码欧洲m码国产av | 亚洲一区二区三区国产精华液 | 亚洲国产精品美女久久久久 | 色欲综合久久中文字幕网 | 国产熟女一区二区三区四区五区 | 精品无码一区二区三区的天堂 | 蜜桃视频韩日免费播放 | 国产成人综合色在线观看网站 | 丰满护士巨好爽好大乳 | 国产精品人人爽人人做我的可爱 | 内射后入在线观看一区 | 国产亚洲精品久久久久久国模美 | 日本一区二区更新不卡 | 亚洲色偷偷男人的天堂 | 人妻与老人中文字幕 | 熟女俱乐部五十路六十路av | 国产激情综合五月久久 | 无码帝国www无码专区色综合 | 秋霞成人午夜鲁丝一区二区三区 | 国产一区二区三区日韩精品 | 亚洲综合精品香蕉久久网 | 亚洲一区二区三区 | 岛国片人妻三上悠亚 | 久久综合久久自在自线精品自 | 成人性做爰aaa片免费看不忠 | 国产电影无码午夜在线播放 | 免费国产黄网站在线观看 | av无码久久久久不卡免费网站 | 55夜色66夜色国产精品视频 | 日本欧美一区二区三区乱码 | 亚洲欧美中文字幕5发布 | 亚洲成av人综合在线观看 | 一个人免费观看的www视频 | 中文字幕av伊人av无码av | 99久久无码一区人妻 | 欧洲欧美人成视频在线 | 99久久人妻精品免费一区 | 蜜桃视频插满18在线观看 | 欧美 亚洲 国产 另类 | 国产99久久精品一区二区 | 国产人妻久久精品二区三区老狼 | 一本色道婷婷久久欧美 | 久久久久久久女国产乱让韩 | 爱做久久久久久 | 人妻无码αv中文字幕久久琪琪布 | 曰本女人与公拘交酡免费视频 | 国产精品美女久久久网av | 欧美国产日韩亚洲中文 | 日本乱人伦片中文三区 | 中文字幕精品av一区二区五区 | 国产精品免费大片 | 精品无码一区二区三区的天堂 | 欧美人与禽猛交狂配 | 精品亚洲韩国一区二区三区 | 亚洲综合在线一区二区三区 | 中文字幕人妻无码一区二区三区 | 国产片av国语在线观看 | 久久久久久av无码免费看大片 | 无码福利日韩神码福利片 | 亚洲色在线无码国产精品不卡 | 无码纯肉视频在线观看 | 偷窥村妇洗澡毛毛多 | 伊人久久婷婷五月综合97色 | 亚洲а∨天堂久久精品2021 | 成人精品视频一区二区三区尤物 | 欧美老妇交乱视频在线观看 | 成人精品一区二区三区中文字幕 | 国内精品久久久久久中文字幕 | 欧美喷潮久久久xxxxx | 特级做a爰片毛片免费69 | 骚片av蜜桃精品一区 | 少妇性l交大片欧洲热妇乱xxx | 日韩成人一区二区三区在线观看 | 国产舌乚八伦偷品w中 | 精品无码成人片一区二区98 | 内射老妇bbwx0c0ck | 日韩精品久久久肉伦网站 | 午夜免费福利小电影 | 国产成人无码av片在线观看不卡 | 曰韩无码二三区中文字幕 | 国产婷婷色一区二区三区在线 | 精品国产青草久久久久福利 | 娇妻被黑人粗大高潮白浆 | 女人被男人躁得好爽免费视频 | 亚洲精品一区三区三区在线观看 | 久久精品国产99精品亚洲 | 久久久久免费精品国产 | 国内综合精品午夜久久资源 | 免费国产成人高清在线观看网站 | 亚洲成av人片在线观看无码不卡 | 亚洲欧美中文字幕5发布 | 国产精品丝袜黑色高跟鞋 | 日本熟妇大屁股人妻 | 久久99国产综合精品 | 大地资源网第二页免费观看 | 久久亚洲精品中文字幕无男同 | 久久这里只有精品视频9 | 少妇被粗大的猛进出69影院 | 天天躁夜夜躁狠狠是什么心态 | 永久黄网站色视频免费直播 | 亚洲精品欧美二区三区中文字幕 | 中文字幕乱码人妻二区三区 | 鲁一鲁av2019在线 | 久久精品国产日本波多野结衣 | 免费乱码人妻系列无码专区 | 黑人大群体交免费视频 | 日本va欧美va欧美va精品 | 人妻少妇精品无码专区二区 | 男女爱爱好爽视频免费看 | 欧美成人免费全部网站 | 中文字幕乱码人妻二区三区 | 国产欧美亚洲精品a | 领导边摸边吃奶边做爽在线观看 | 国产乱码精品一品二品 | 亚洲成av人影院在线观看 | 中文字幕无码日韩专区 | 午夜无码人妻av大片色欲 | 久久精品国产99久久6动漫 | 国产人成高清在线视频99最全资源 | 人妻aⅴ无码一区二区三区 | 丰满少妇熟乱xxxxx视频 | 暴力强奷在线播放无码 | 国产激情艳情在线看视频 | 亚洲熟妇色xxxxx欧美老妇y | 中国女人内谢69xxxx | 国产精品99爱免费视频 | 丰满人妻翻云覆雨呻吟视频 | 在线观看国产午夜福利片 | 精品厕所偷拍各类美女tp嘘嘘 | 在线播放免费人成毛片乱码 | 欧美丰满熟妇xxxx性ppx人交 | 日日摸夜夜摸狠狠摸婷婷 | 奇米影视7777久久精品人人爽 | 人人妻人人澡人人爽人人精品浪潮 | 欧美日韩一区二区免费视频 | 久久精品99久久香蕉国产色戒 | 欧美人与牲动交xxxx | 成人精品视频一区二区三区尤物 | 国产av人人夜夜澡人人爽麻豆 | 综合人妻久久一区二区精品 | 亚洲精品国产第一综合99久久 | 亚洲乱亚洲乱妇50p | 成年美女黄网站色大免费视频 | 最近中文2019字幕第二页 | 精品乱子伦一区二区三区 | 国产偷抇久久精品a片69 | 成人无码精品1区2区3区免费看 | 日日躁夜夜躁狠狠躁 | 国产人妻精品一区二区三区不卡 | 日本熟妇人妻xxxxx人hd | 帮老师解开蕾丝奶罩吸乳网站 | 又粗又大又硬毛片免费看 | 免费人成网站视频在线观看 | 性色欲网站人妻丰满中文久久不卡 | 亚洲精品无码人妻无码 | 色欲久久久天天天综合网精品 | 一本久道久久综合狠狠爱 | 午夜男女很黄的视频 | 国产绳艺sm调教室论坛 | 在线精品亚洲一区二区 | 暴力强奷在线播放无码 | 狂野欧美激情性xxxx | 1000部啪啪未满十八勿入下载 | 国产精品久久久久影院嫩草 | 狠狠噜狠狠狠狠丁香五月 | 熟女少妇人妻中文字幕 | 亚洲乱亚洲乱妇50p | 国产亚洲日韩欧美另类第八页 | 国内揄拍国内精品人妻 | 精品国产一区二区三区av 性色 | 国产无av码在线观看 | 伊人久久婷婷五月综合97色 | 午夜精品久久久内射近拍高清 | 成人免费视频一区二区 | 狂野欧美性猛xxxx乱大交 | 香蕉久久久久久av成人 | aa片在线观看视频在线播放 | 国产精品亚洲专区无码不卡 | 久久综合香蕉国产蜜臀av | 精品无码成人片一区二区98 | 久久人人爽人人爽人人片av高清 | www国产亚洲精品久久久日本 | 在线观看免费人成视频 | 成年美女黄网站色大免费全看 | 国产另类ts人妖一区二区 | 国产卡一卡二卡三 | 狂野欧美性猛xxxx乱大交 | 国产特级毛片aaaaaa高潮流水 | 久久综合狠狠综合久久综合88 | 丰满少妇弄高潮了www | 国产免费观看黄av片 | 国产熟妇另类久久久久 | 少女韩国电视剧在线观看完整 | 人妻天天爽夜夜爽一区二区 | 免费乱码人妻系列无码专区 | 又大又硬又黄的免费视频 | 欧美 亚洲 国产 另类 | 免费人成网站视频在线观看 | 欧美日韩人成综合在线播放 | 精品厕所偷拍各类美女tp嘘嘘 | 精品人人妻人人澡人人爽人人 | 玩弄少妇高潮ⅹxxxyw | 久久亚洲国产成人精品性色 | 国产精品igao视频网 | 青青久在线视频免费观看 | 日韩无套无码精品 | 中文字幕乱码亚洲无线三区 | 亚洲天堂2017无码 | 中文字幕无线码 | 精品日本一区二区三区在线观看 | 亚洲精品一区二区三区四区五区 | 少妇性l交大片欧洲热妇乱xxx | 国语自产偷拍精品视频偷 | 久久综合狠狠综合久久综合88 | 亚洲精品欧美二区三区中文字幕 | 国产av无码专区亚洲a∨毛片 | 丰满岳乱妇在线观看中字无码 | 亚洲国产欧美日韩精品一区二区三区 | 国精品人妻无码一区二区三区蜜柚 | 久久精品国产大片免费观看 | 免费无码一区二区三区蜜桃大 | 在线亚洲高清揄拍自拍一品区 | 亚无码乱人伦一区二区 | 综合激情五月综合激情五月激情1 | 亚洲精品国偷拍自产在线麻豆 | 麻豆人妻少妇精品无码专区 | 激情亚洲一区国产精品 | 国产农村妇女高潮大叫 | 蜜桃臀无码内射一区二区三区 | 国产精品无码久久av | 久久综合狠狠综合久久综合88 | 国产xxx69麻豆国语对白 | 乌克兰少妇xxxx做受 | 少妇性俱乐部纵欲狂欢电影 | 国产午夜无码精品免费看 | 亚洲自偷精品视频自拍 | 中文字幕无码av激情不卡 | 精品成人av一区二区三区 | 日本熟妇浓毛 | 少妇性l交大片欧洲热妇乱xxx | 精品熟女少妇av免费观看 | 99国产欧美久久久精品 | 欧美人妻一区二区三区 | 成人性做爰aaa片免费看 | 国产香蕉97碰碰久久人人 | 国内少妇偷人精品视频免费 | 精品夜夜澡人妻无码av蜜桃 | 精品无人区无码乱码毛片国产 | 亚洲国产精品久久人人爱 | 久久久久久亚洲精品a片成人 | 久久99精品久久久久久动态图 | 国产精品沙发午睡系列 | 成人试看120秒体验区 | 大色综合色综合网站 | 亚洲色成人中文字幕网站 | 精品国偷自产在线 | 国产精品高潮呻吟av久久4虎 | 99riav国产精品视频 | 俺去俺来也在线www色官网 | 牲欲强的熟妇农村老妇女视频 | 兔费看少妇性l交大片免费 | 色婷婷欧美在线播放内射 | 国产成人精品一区二区在线小狼 | 国产成人无码一二三区视频 | 久久无码专区国产精品s | 高潮毛片无遮挡高清免费 | 国产精品99久久精品爆乳 | 精品一区二区三区波多野结衣 | 欧洲vodafone精品性 | 一本大道久久东京热无码av | 99国产精品白浆在线观看免费 | 午夜成人1000部免费视频 | 国产成人久久精品流白浆 | 波多野结衣乳巨码无在线观看 | 综合人妻久久一区二区精品 | 天天做天天爱天天爽综合网 | 男女下面进入的视频免费午夜 | 欧美真人作爱免费视频 | 午夜精品久久久内射近拍高清 | 人妻尝试又大又粗久久 | 中文字幕无码日韩专区 | 欧美精品一区二区精品久久 | 国产综合在线观看 | 丰满人妻翻云覆雨呻吟视频 | 国产欧美亚洲精品a | 无码帝国www无码专区色综合 | 国产精品-区区久久久狼 | 国产精品久久久久9999小说 | 天堂一区人妻无码 | 国产无套粉嫩白浆在线 | 国产成人无码av片在线观看不卡 | 午夜成人1000部免费视频 | 人妻少妇精品无码专区二区 | 日本精品高清一区二区 | 色一情一乱一伦一视频免费看 | 亚洲综合伊人久久大杳蕉 | 日本乱偷人妻中文字幕 | 午夜丰满少妇性开放视频 | 人妻中文无码久热丝袜 | 最近的中文字幕在线看视频 | 欧美精品一区二区精品久久 | 中文亚洲成a人片在线观看 | 十八禁视频网站在线观看 | 俺去俺来也在线www色官网 | 国产艳妇av在线观看果冻传媒 | 捆绑白丝粉色jk震动捧喷白浆 | 色婷婷欧美在线播放内射 | yw尤物av无码国产在线观看 | 又大又黄又粗又爽的免费视频 | 一本无码人妻在中文字幕免费 | 樱花草在线播放免费中文 | 国产乱人偷精品人妻a片 | 福利一区二区三区视频在线观看 | 成熟女人特级毛片www免费 | 成人无码视频在线观看网站 | 国产精品久久久久影院嫩草 | 亚洲va中文字幕无码久久不卡 | 久久精品国产日本波多野结衣 | 久久久国产一区二区三区 | 国产偷抇久久精品a片69 | 性欧美疯狂xxxxbbbb | 中文字幕乱码亚洲无线三区 | 97精品人妻一区二区三区香蕉 | 少妇激情av一区二区 | 久久久无码中文字幕久... | 国产性生交xxxxx无码 | √天堂中文官网8在线 | 桃花色综合影院 | 国产高清不卡无码视频 | 国产极品美女高潮无套在线观看 | 日本在线高清不卡免费播放 | 女人被男人爽到呻吟的视频 | 成人av无码一区二区三区 | 一本无码人妻在中文字幕免费 | 日本护士xxxxhd少妇 | 成人性做爰aaa片免费看不忠 | 日日噜噜噜噜夜夜爽亚洲精品 | 久久人人爽人人爽人人片ⅴ | 国产精品高潮呻吟av久久 | 亚洲中文字幕av在天堂 | 精品亚洲成av人在线观看 | 久久精品国产99精品亚洲 | 国产精品高潮呻吟av久久4虎 | 欧美亚洲国产一区二区三区 | 无套内谢的新婚少妇国语播放 | 午夜精品久久久内射近拍高清 | 亚洲性无码av中文字幕 | 日韩精品成人一区二区三区 | 中文字幕av无码一区二区三区电影 | 久久久精品国产sm最大网站 | 老司机亚洲精品影院无码 | 亚洲国产精华液网站w | 国产成人综合在线女婷五月99播放 | 亚洲 日韩 欧美 成人 在线观看 | 欧美丰满老熟妇xxxxx性 | 亚洲日本在线电影 | 日韩 欧美 动漫 国产 制服 | 亚洲天堂2017无码 | 午夜成人1000部免费视频 | 亚洲精品中文字幕乱码 | 久久久久国色av免费观看性色 | 日日躁夜夜躁狠狠躁 | 国产熟女一区二区三区四区五区 | 亚洲大尺度无码无码专区 | 人妻尝试又大又粗久久 | 久久精品99久久香蕉国产色戒 | 日韩成人一区二区三区在线观看 | 午夜精品一区二区三区的区别 | 在线欧美精品一区二区三区 | 国产亚洲精品精品国产亚洲综合 | 亚洲熟妇色xxxxx欧美老妇 | 精品成人av一区二区三区 | 久久国产自偷自偷免费一区调 | 国产精品高潮呻吟av久久 | 麻豆精产国品 | 国语精品一区二区三区 | 亚洲码国产精品高潮在线 | 亚洲国产精品无码久久久久高潮 | 丰满人妻被黑人猛烈进入 | 成人影院yy111111在线观看 | 久久精品女人天堂av免费观看 | 久久99精品国产麻豆蜜芽 | 国产精品第一区揄拍无码 | 亚洲精品成a人在线观看 | 国产精品人妻一区二区三区四 | 亚洲精品一区二区三区四区五区 | 欧美日韩在线亚洲综合国产人 | 波多野结衣av在线观看 | 荫蒂添的好舒服视频囗交 | 未满小14洗澡无码视频网站 | 国产精品国产三级国产专播 | 亚洲伊人久久精品影院 | 97资源共享在线视频 | 国产午夜亚洲精品不卡下载 | 亚洲日韩精品欧美一区二区 | 国产精品人人爽人人做我的可爱 | 亚洲一区二区三区在线观看网站 | 成人精品天堂一区二区三区 | 精品亚洲成av人在线观看 | 熟妇激情内射com | 精品国产一区二区三区av 性色 | 久久精品国产一区二区三区 | 国产成人精品久久亚洲高清不卡 | 女人色极品影院 | 日日天日日夜日日摸 | 国产乱人偷精品人妻a片 | 内射后入在线观看一区 | 国产人成高清在线视频99最全资源 | 高中生自慰www网站 | 亚洲精品鲁一鲁一区二区三区 | 色一情一乱一伦一视频免费看 | 人人超人人超碰超国产 | 中文字幕av日韩精品一区二区 | 帮老师解开蕾丝奶罩吸乳网站 | 中文字幕无码人妻少妇免费 | 好男人www社区 | 欧美日韩精品 | 精品无码一区二区三区爱欲 | 亚洲区小说区激情区图片区 | 亚洲国产高清在线观看视频 | 国产成人人人97超碰超爽8 | 国产猛烈高潮尖叫视频免费 | 超碰97人人射妻 | 成人欧美一区二区三区 | 欧美肥老太牲交大战 | 在线播放无码字幕亚洲 | 日日鲁鲁鲁夜夜爽爽狠狠 | 熟妇激情内射com | 无码国内精品人妻少妇 | 丰满人妻一区二区三区免费视频 | 国产福利视频一区二区 | 一本久道久久综合婷婷五月 | 天天躁夜夜躁狠狠是什么心态 | 国产激情精品一区二区三区 | 午夜精品久久久久久久久 | 国产午夜手机精彩视频 | 国产明星裸体无码xxxx视频 | 国产精品va在线观看无码 | 久久久久av无码免费网 | 欧美激情内射喷水高潮 | 国产亚洲精品久久久久久大师 | 精品夜夜澡人妻无码av蜜桃 | 成人av无码一区二区三区 | 少妇性l交大片欧洲热妇乱xxx | 欧美日韩一区二区综合 | 久久久久久九九精品久 | 亚洲欧洲日本综合aⅴ在线 | 夜夜躁日日躁狠狠久久av | 亚洲爆乳大丰满无码专区 | 人人妻人人澡人人爽精品欧美 | 无人区乱码一区二区三区 | 亚洲成av人在线观看网址 | 亚洲一区二区三区四区 | 精品欧洲av无码一区二区三区 | 亚洲一区二区三区香蕉 | 国产精品久久精品三级 | 国产亚洲人成在线播放 | 欧美xxxx黑人又粗又长 | 国产人妻大战黑人第1集 | 天堂久久天堂av色综合 | 双乳奶水饱满少妇呻吟 | 日日橹狠狠爱欧美视频 | 欧美第一黄网免费网站 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 婷婷色婷婷开心五月四房播播 | 无套内谢的新婚少妇国语播放 | 欧美老妇交乱视频在线观看 | 色情久久久av熟女人妻网站 | 亚洲人亚洲人成电影网站色 | 国产激情无码一区二区app | 久久97精品久久久久久久不卡 | 欧美35页视频在线观看 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 好男人社区资源 | 人人妻人人藻人人爽欧美一区 | 久久精品人妻少妇一区二区三区 | 免费人成网站视频在线观看 | 久久综合狠狠综合久久综合88 | 又大又硬又黄的免费视频 | 激情亚洲一区国产精品 | 捆绑白丝粉色jk震动捧喷白浆 | 久久精品女人天堂av免费观看 | 亚洲精品一区二区三区婷婷月 | 国内少妇偷人精品视频 | 天海翼激烈高潮到腰振不止 | 亚洲 日韩 欧美 成人 在线观看 | 丝袜足控一区二区三区 | 久久99精品国产.久久久久 | 精品人妻av区 | 久久婷婷五月综合色国产香蕉 | 人人妻人人澡人人爽欧美精品 | 欧美熟妇另类久久久久久不卡 | 强伦人妻一区二区三区视频18 | 亚洲aⅴ无码成人网站国产app | 水蜜桃av无码 | 色综合久久久无码网中文 | 国产偷国产偷精品高清尤物 | 亚洲欧美日韩成人高清在线一区 | 亚洲国产av美女网站 | 国产成人无码午夜视频在线观看 | 在线播放无码字幕亚洲 | 久久亚洲精品成人无码 | 一二三四社区在线中文视频 | 久久精品人人做人人综合试看 | 中文字幕乱妇无码av在线 | 国产精品国产自线拍免费软件 | 久久久久久亚洲精品a片成人 | 极品尤物被啪到呻吟喷水 | 久久久久99精品成人片 | 亚洲欧美综合区丁香五月小说 | 天天综合网天天综合色 | 亚洲小说图区综合在线 | 免费人成在线视频无码 | 无码精品国产va在线观看dvd | 蜜臀av在线播放 久久综合激激的五月天 | 一个人免费观看的www视频 | 无码人妻丰满熟妇区毛片18 | 日韩av无码中文无码电影 | 国产麻豆精品精东影业av网站 | 亚洲娇小与黑人巨大交 | 亚洲s色大片在线观看 | 少妇激情av一区二区 | 男女超爽视频免费播放 | 永久免费精品精品永久-夜色 | 日日碰狠狠躁久久躁蜜桃 | 国产成人综合色在线观看网站 | 天天摸天天碰天天添 | 亚洲综合无码久久精品综合 | 麻豆蜜桃av蜜臀av色欲av | 国产美女极度色诱视频www | 亚洲国产精品一区二区第一页 | av无码电影一区二区三区 | 免费乱码人妻系列无码专区 | 国产精品亚洲一区二区三区喷水 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 3d动漫精品啪啪一区二区中 | 国产一区二区三区四区五区加勒比 | 国产艳妇av在线观看果冻传媒 | 亚洲人成无码网www | 久久久久久av无码免费看大片 | 狂野欧美性猛xxxx乱大交 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 无码av岛国片在线播放 | 强伦人妻一区二区三区视频18 | 久久久精品国产sm最大网站 | 亚洲精品综合一区二区三区在线 | 精品国产av色一区二区深夜久久 | 日日摸夜夜摸狠狠摸婷婷 | 国内丰满熟女出轨videos | 天堂无码人妻精品一区二区三区 | 国产精品美女久久久 | 又大又黄又粗又爽的免费视频 | 超碰97人人做人人爱少妇 | 国内丰满熟女出轨videos | 亚洲乱码国产乱码精品精 | 女人和拘做爰正片视频 | 精品久久久久久亚洲精品 | 国产成人综合在线女婷五月99播放 | 色老头在线一区二区三区 | 在线播放免费人成毛片乱码 | 久久国产劲爆∧v内射 | 四虎永久在线精品免费网址 | 无码人妻少妇伦在线电影 | 国产成人久久精品流白浆 | 欧美精品免费观看二区 | 国产香蕉尹人综合在线观看 | 中文字幕亚洲情99在线 | 国产两女互慰高潮视频在线观看 | 一本一道久久综合久久 | 水蜜桃色314在线观看 | 欧美老熟妇乱xxxxx | 高中生自慰www网站 | 精品日本一区二区三区在线观看 | 最近免费中文字幕中文高清百度 | 中文字幕久久久久人妻 | 无码人中文字幕 | 国产97在线 | 亚洲 | 日本精品高清一区二区 | 妺妺窝人体色www在线小说 | 国产超碰人人爽人人做人人添 | 99er热精品视频 | 久久精品视频在线看15 | 大屁股大乳丰满人妻 | 亚洲日韩av一区二区三区中文 | 大地资源网第二页免费观看 | 欧美老妇交乱视频在线观看 | 国产精品无码一区二区三区不卡 | 亚洲无人区午夜福利码高清完整版 | 国产精品国产自线拍免费软件 | 四十如虎的丰满熟妇啪啪 | 狠狠色丁香久久婷婷综合五月 | 日本熟妇大屁股人妻 | 噜噜噜亚洲色成人网站 | 亚洲狠狠婷婷综合久久 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 在线а√天堂中文官网 | 国产凸凹视频一区二区 | 亚洲性无码av中文字幕 | 人妻少妇精品无码专区动漫 | 在线a亚洲视频播放在线观看 | 熟妇女人妻丰满少妇中文字幕 | 无码精品人妻一区二区三区av | 久久久婷婷五月亚洲97号色 | 亚洲热妇无码av在线播放 | 免费男性肉肉影院 | 中文字幕无码av激情不卡 | 亚洲精品中文字幕乱码 | 国产免费观看黄av片 | 国产午夜福利亚洲第一 | 欧美乱妇无乱码大黄a片 | 国精产品一品二品国精品69xx | 在教室伦流澡到高潮hnp视频 | 欧美性猛交内射兽交老熟妇 | 天天躁夜夜躁狠狠是什么心态 | 老熟妇乱子伦牲交视频 | 免费视频欧美无人区码 | 日本丰满护士爆乳xxxx | 国产精品久久久久影院嫩草 | 一本久久a久久精品亚洲 | 国产电影无码午夜在线播放 | 乱人伦人妻中文字幕无码久久网 | 日韩少妇内射免费播放 | 窝窝午夜理论片影院 | 亚洲精品美女久久久久久久 | 在线观看免费人成视频 | 亚洲综合色区中文字幕 | 无码免费一区二区三区 | 亚洲欧美精品伊人久久 | 国产色视频一区二区三区 | 小泽玛莉亚一区二区视频在线 | 色婷婷香蕉在线一区二区 | 宝宝好涨水快流出来免费视频 | 最新国产麻豆aⅴ精品无码 | 九月婷婷人人澡人人添人人爽 | 又大又黄又粗又爽的免费视频 | 久久综合色之久久综合 | 搡女人真爽免费视频大全 | 中文字幕久久久久人妻 | 亚洲熟熟妇xxxx | 亚洲人成影院在线观看 | 日本欧美一区二区三区乱码 | 国产真实夫妇视频 | 人妻人人添人妻人人爱 | 好男人www社区 | 俺去俺来也在线www色官网 | 未满小14洗澡无码视频网站 | 又大又紧又粉嫩18p少妇 | 国产亚洲精品久久久久久国模美 | 97色伦图片97综合影院 | 老熟女乱子伦 | 人人妻人人澡人人爽欧美一区九九 | 无码精品人妻一区二区三区av | 东京热男人av天堂 | 东北女人啪啪对白 | 亚洲国产精品一区二区第一页 | 十八禁真人啪啪免费网站 | 少妇性俱乐部纵欲狂欢电影 | 国产精品人人爽人人做我的可爱 | 性欧美牲交xxxxx视频 | 夫妻免费无码v看片 | 欧美性生交活xxxxxdddd | 久久久国产精品无码免费专区 | 亚洲熟悉妇女xxx妇女av | 无码人妻精品一区二区三区下载 | 麻豆国产人妻欲求不满谁演的 | 偷窥村妇洗澡毛毛多 | 国产亚洲美女精品久久久2020 | 久久综合狠狠综合久久综合88 | 久久精品丝袜高跟鞋 | 亚洲综合在线一区二区三区 | 国产一区二区三区精品视频 | 国产乱码精品一品二品 | 天堂а√在线地址中文在线 | 久久国产36精品色熟妇 | 亚洲自偷精品视频自拍 | v一区无码内射国产 | 国产精品亚洲а∨无码播放麻豆 | 久久午夜夜伦鲁鲁片无码免费 | 国产内射老熟女aaaa | 伊人久久婷婷五月综合97色 | 久久精品国产亚洲精品 | 国产精品成人av在线观看 | 超碰97人人射妻 | 亚洲人亚洲人成电影网站色 | 国产精品久久国产精品99 | 色窝窝无码一区二区三区色欲 | 67194成是人免费无码 | 蜜桃av抽搐高潮一区二区 | 中文字幕亚洲情99在线 | 成人一区二区免费视频 | 网友自拍区视频精品 | 久久精品国产精品国产精品污 | 高清无码午夜福利视频 | 黑人玩弄人妻中文在线 | 亚洲综合精品香蕉久久网 | 国产日产欧产精品精品app | 国产午夜视频在线观看 | 一本色道婷婷久久欧美 | 色一情一乱一伦一区二区三欧美 | 国产人妻精品一区二区三区 | 久久综合九色综合97网 | 久久午夜无码鲁丝片午夜精品 | 99riav国产精品视频 | 国产农村妇女高潮大叫 | 天天拍夜夜添久久精品大 | 全黄性性激高免费视频 | 国产无av码在线观看 | 亚洲自偷自偷在线制服 | 欧美日韩人成综合在线播放 | 扒开双腿疯狂进出爽爽爽视频 | 国产精品久久国产精品99 | 亚洲gv猛男gv无码男同 | 午夜精品一区二区三区的区别 | 午夜福利试看120秒体验区 | 亚洲成av人影院在线观看 | 日韩成人一区二区三区在线观看 | 亚洲综合色区中文字幕 | 亚洲成a人片在线观看无码3d | 免费人成网站视频在线观看 | 精品久久8x国产免费观看 | 亚洲乱码中文字幕在线 | 麻豆果冻传媒2021精品传媒一区下载 | 亚洲一区二区三区偷拍女厕 | 激情爆乳一区二区三区 | 国产成人无码a区在线观看视频app | 国产精品久久精品三级 | 亚洲精品一区国产 | 日本精品人妻无码免费大全 | 国产午夜无码精品免费看 | 精品偷自拍另类在线观看 | 白嫩日本少妇做爰 | 无码人妻精品一区二区三区下载 | 无码中文字幕色专区 | 一本久道久久综合狠狠爱 | 亚洲国产欧美在线成人 | 九九热爱视频精品 | 少妇人妻偷人精品无码视频 | 国产激情艳情在线看视频 | 狠狠躁日日躁夜夜躁2020 | 无遮挡国产高潮视频免费观看 | 久久天天躁狠狠躁夜夜免费观看 | 国产真人无遮挡作爱免费视频 | 亚洲欧美精品伊人久久 | 乱人伦中文视频在线观看 | 国产午夜亚洲精品不卡 | 大乳丰满人妻中文字幕日本 | 无码人妻出轨黑人中文字幕 | 人妻夜夜爽天天爽三区 | av在线亚洲欧洲日产一区二区 | 国产精品18久久久久久麻辣 | 国产精品久久久久无码av色戒 | 久久人人爽人人人人片 | 亚洲精品综合五月久久小说 | 亚洲综合精品香蕉久久网 | 色情久久久av熟女人妻网站 | 激情内射日本一区二区三区 | 日本熟妇大屁股人妻 | 国产免费久久久久久无码 | 黑人粗大猛烈进出高潮视频 | 999久久久国产精品消防器材 | 日本乱偷人妻中文字幕 | 亚洲精品国产a久久久久久 | 成人三级无码视频在线观看 | www一区二区www免费 | 天堂亚洲免费视频 | 熟妇女人妻丰满少妇中文字幕 | 2019nv天堂香蕉在线观看 | 亚洲国产成人av在线观看 | 亚洲阿v天堂在线 | 亚洲精品国产第一综合99久久 | 免费中文字幕日韩欧美 | 玩弄少妇高潮ⅹxxxyw | 亚洲精品国产品国语在线观看 | 精品成在人线av无码免费看 | 丝袜美腿亚洲一区二区 | 中文字幕无码日韩欧毛 | 精品久久久无码中文字幕 | 波多野结衣一区二区三区av免费 | 国产高清av在线播放 | 波多野结衣aⅴ在线 | 欧洲vodafone精品性 | 好爽又高潮了毛片免费下载 | 亚洲欧洲中文日韩av乱码 | 亚洲色大成网站www国产 | 日韩精品无码一本二本三本色 | 黑森林福利视频导航 | 自拍偷自拍亚洲精品10p | 日日天干夜夜狠狠爱 | 久久久精品人妻久久影视 | 久9re热视频这里只有精品 | 国产又爽又黄又刺激的视频 | 国产精品美女久久久久av爽李琼 | 风流少妇按摩来高潮 | yw尤物av无码国产在线观看 | 精品一二三区久久aaa片 | 国内综合精品午夜久久资源 | 人妻中文无码久热丝袜 | 亚洲大尺度无码无码专区 | 国产成人久久精品流白浆 | 思思久久99热只有频精品66 | 成人亚洲精品久久久久 | 天堂а√在线中文在线 | 国产激情艳情在线看视频 | 久久精品中文字幕大胸 | 亚洲爆乳大丰满无码专区 | 少妇愉情理伦片bd | 中文字幕日产无线码一区 | 大地资源网第二页免费观看 | 高潮毛片无遮挡高清免费 | 欧美日韩亚洲国产精品 | 国产人妻精品一区二区三区不卡 | 国内精品久久毛片一区二区 | 无码任你躁久久久久久久 | 亚洲成a人片在线观看无码3d | 无码人中文字幕 | 国产美女精品一区二区三区 | 无码国产乱人伦偷精品视频 | yw尤物av无码国产在线观看 | 在线亚洲高清揄拍自拍一品区 | 国产精品资源一区二区 | 日本丰满护士爆乳xxxx | 永久免费精品精品永久-夜色 | 老熟妇仑乱视频一区二区 | 欧洲vodafone精品性 | 日韩成人一区二区三区在线观看 | 7777奇米四色成人眼影 | 欧美猛少妇色xxxxx | 偷窥村妇洗澡毛毛多 | 人人妻人人澡人人爽欧美一区 | 97久久超碰中文字幕 | 狠狠色噜噜狠狠狠狠7777米奇 | 亚洲国产高清在线观看视频 | 熟妇人妻激情偷爽文 | 乱人伦中文视频在线观看 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 麻豆果冻传媒2021精品传媒一区下载 | 偷窥日本少妇撒尿chinese | 欧洲精品码一区二区三区免费看 | 久久久www成人免费毛片 | 97se亚洲精品一区 | 国产手机在线αⅴ片无码观看 | 国产成人亚洲综合无码 | 亚洲啪av永久无码精品放毛片 | 爆乳一区二区三区无码 | 久久午夜无码鲁丝片午夜精品 | 久久久久久亚洲精品a片成人 | 亚洲成a人一区二区三区 | 国产莉萝无码av在线播放 | 麻豆成人精品国产免费 | 在线精品亚洲一区二区 | 永久黄网站色视频免费直播 | 午夜男女很黄的视频 | 久久精品一区二区三区四区 | 麻豆国产97在线 | 欧洲 | 欧美xxxx黑人又粗又长 | 人妻人人添人妻人人爱 | 国产精品无码一区二区桃花视频 | 日韩精品无码免费一区二区三区 | 色婷婷欧美在线播放内射 | 两性色午夜免费视频 | 亚洲精品久久久久久久久久久 | 亚洲熟悉妇女xxx妇女av | 中文字幕无码视频专区 | 亚洲最大成人网站 | 精品久久久无码中文字幕 | 久久久久久久久蜜桃 | 成人无码影片精品久久久 | 蜜桃臀无码内射一区二区三区 | av小次郎收藏 | 天天av天天av天天透 | 亚洲国产精品一区二区第一页 | 欧美人与牲动交xxxx | 久久国产精品偷任你爽任你 | 久久综合九色综合97网 | 国产成人无码区免费内射一片色欲 | 欧美日本精品一区二区三区 | ass日本丰满熟妇pics | 精品无码成人片一区二区98 | 男女超爽视频免费播放 | 人人爽人人澡人人高潮 | 东京一本一道一二三区 | 一本久道高清无码视频 | 曰韩无码二三区中文字幕 | 天堂无码人妻精品一区二区三区 | 99在线 | 亚洲 | 日本一卡二卡不卡视频查询 | 国产人妻人伦精品 | 国产精品理论片在线观看 | 国产美女精品一区二区三区 | 无码免费一区二区三区 | 成熟妇人a片免费看网站 | 亚洲自偷自偷在线制服 | 久久综合给久久狠狠97色 | 99久久久无码国产aaa精品 | 国产亚洲精品久久久久久久久动漫 | 99久久人妻精品免费二区 | 美女扒开屁股让男人桶 | 色狠狠av一区二区三区 | 熟妇激情内射com | 精品欧美一区二区三区久久久 | 无码人妻精品一区二区三区下载 | 国产激情精品一区二区三区 | 人人妻人人澡人人爽精品欧美 | 亚洲成熟女人毛毛耸耸多 | 日韩在线不卡免费视频一区 | 国产精品久免费的黄网站 | 乱人伦中文视频在线观看 | 亚洲欧美国产精品久久 | 国产成人精品一区二区在线小狼 | 亚洲人成网站色7799 | 四虎永久在线精品免费网址 | 亚洲精品国产品国语在线观看 | 欧美zoozzooz性欧美 | 天下第一社区视频www日本 | 日韩人妻无码一区二区三区久久99 | 日本丰满护士爆乳xxxx | 日日鲁鲁鲁夜夜爽爽狠狠 | 人妻aⅴ无码一区二区三区 | 一个人看的www免费视频在线观看 | 无码播放一区二区三区 | 日本肉体xxxx裸交 | 国产亚洲欧美在线专区 | 秋霞特色aa大片 | 国产精品久久久 | a在线亚洲男人的天堂 | 亚洲日韩精品欧美一区二区 | 中文字幕精品av一区二区五区 | 麻豆人妻少妇精品无码专区 | 丰满岳乱妇在线观看中字无码 | 黑人巨大精品欧美一区二区 | 国产精品资源一区二区 | 日韩少妇内射免费播放 | 国内揄拍国内精品人妻 | 亚洲成a人片在线观看无码 | 国产精品二区一区二区aⅴ污介绍 | 强开小婷嫩苞又嫩又紧视频 | 激情内射亚州一区二区三区爱妻 | 国产精品久免费的黄网站 | 在线а√天堂中文官网 | 亚洲国产欧美日韩精品一区二区三区 | 婷婷五月综合激情中文字幕 | 一本加勒比波多野结衣 | 中文字幕日韩精品一区二区三区 | 国产一区二区三区精品视频 | 国产又粗又硬又大爽黄老大爷视 |