LCODER之JNI系列: C++基础

241 阅读14分钟
写在前面:

C\C++基础,两篇文章,是本人学习C\C++的学习笔记。比较实用,没有太多理论上的描述,需要仔细看的是一些代码的注释。C\C++是JNI的基础,这两篇学习笔记看完之后,应该能对C\C++有一个初步的了解,为后续学习JNI打下一些基础。

一、 C++初级

1.C++版 HelloWorld

#include <iostream> 
using namespace std; 
int main()
{ 
std::cout << "Hello, World!" << std::endl; 
cout << "C++" << endl; // 上面引入了命名空间,这里就可以省略std:: // endl 换行的意思 
cout << "" << endl; 
cout << "\n" << "\n" << "\n"; 
return 0;
}

2.引用

3.深拷贝和浅拷贝

4.this关键字

#include <iostream>
using namespace std;
class Student{
private:
    char * name;
    int age;

public:
    void setName(char * name){
        this->name = name;
    }

    void setAge(int age){
        this->age = age;
    }

    char * getName(){
        return this->name;
    }

    int getAge(){
        return this->age;
    }

    // 声明一个静态变量
    static int id; // 先声明


    // 这里还有一个默认的构造函数 会在栈区开辟空间 暴露 this 指针
};

// 再实现
int Student::id = 9527;

int main(){
    Student student;
    student.setAge(99);
    cout << student.getAge() << endl;

    Student student1;
    student1.setAge(88);
    student1.id = 990;
    cout << student1.getAge() << endl;

    Student student2;
    student2.setAge(77);
    student2.id = 880;
    cout << student2.getAge() << endl;

    return 0;
}
由上述代码引发的思考:为什么设置age可以准确的设置到student和student1、student2中?

每new出一个student,就会在栈区开辟出一块空间,每个student 会有一个默认的构造函数,暴露this指针。this指针会指向代码区,这个区域存放getAge的函数主体,每个Student的this指针都指向代码区域的副本。 静态区没有this的概念,只有一块区域,每次更改值都会改变静态区的id。如下图所示:

图1

const修饰函数的this意义何在
#include <iostream>

using namespace std;

//类型  * const  指针常量  地址所对应的值能改,但是地址不能改
// const 类型 * 常量指针  不允许修改指针地址所对应的值,可以去修改地址
// const 类型 * const 常量指针常量 什么都不能改 地址不能改 地址对应的值也不能改

class Worker{
public:
    char * name;
    int age = NULL; // C++中,没有默认值,如果不给默认值,默认值是系统值 -64664

    void change1(){
        // 为什么可以修改age?
        // 这个函数里默认持有了隐式的this指针 并且会这样修饰 Worker * const this
        // 类型 * const 指针常量 : 代表指针地址不能被修改,但是指针地址的值是可以修改的

        // this = 0x6546; // 指针常量的值不能被修改,编译不通过
        // 但是指针地址指向的值是可以修改的
        this->age = 100;
    }

    void change2() const{
        // 现在 this等价于const Worker * const  常量指针常量 
        // 常量指针常量: 什么都不能改 地址不能改 地址对应的值也不能改            
    }
};

6.友元函数

一般函数无法访问类中的私有成员,但是友元函数是类的好朋友,可以访问类中的私有成员

#include <iostream>
using namespace std;
class Person{
 private: // 私有的age,外界不能访问
    int age = 0;

public:
    Person(int age) {
        this->age = age;
    }

    int getAge() {
        return this->age;
    }

    // 定义友元函数 (声明,没有实现)
    friend void updateAge(Person * person, int age);
}
// 友元函数的实现,可以访问所以私有成员
void updateAge(Person* person, int age) {
    // 默认情况下:不能修改 私有的age
    // 谁有这个权限:友元(拿到所有私有成员)
    person->age = age;
}
int main() {
    Person person = Person(9);
    updateAge(&person, 88);  // 调用updateAge

    cout << person.getAge() << endl;
    return 0;
}

6.静态函数,友元函数,普通函数,构造函数,析构函数,拷贝构造函数,有啥区别?

pig.h

#include <iostream>

using namespace std;

// JNI 为什么一定要用这个东西(后面专门)

#ifndef PIG_H // 你有没有这个宏(Java 宏==常量)
#define PIG_H // 定义这个宏

class Pig {
private:
    int age;
    char * name;

public:
    // 静态成员声明
    static int id;

    // 构造函数的声明系列
    Pig();
    Pig(char *);
    Pig(char *,int);

    // 析构函数
    ~Pig();

    // 拷贝构造函数
    Pig(const Pig & pig);

    // 普通函数 set get
    int getAge();
    char * getName();
    void setAge(int);
    void setName(char *);

    void showPigInfo() const; // 常量指针常量 只读

    // 静态函数的声明
    static void changeTag(int age);

    // 不要这样干
    // void changeTag(int age);

    // 友元函数的声明
    friend void changeAge(Pig * pig, int age);
};

#endif // 关闭/结尾

pig.cpp : 对头文件中定义的方法的实现

#include "Pig.h"

// TODO  ======================  下面是 普普通通 常规操作 对象::

// 实现构造函数
Pig::Pig() {
    cout << "默认构造函数" << endl;
}

Pig::Pig(char * name) {
    cout << "1个参数构造函数" << endl;
}

Pig::Pig(char * name, int age) {
    cout << "2个参数构造函数" << endl;
}

// 实现析构函数
Pig::~Pig() {
    cout << "析构函数" << endl;
}

// 实现 拷贝构造函数
Pig::Pig(const Pig &pig) {
    cout << "拷贝构造函数" << endl;
}

int Pig::getAge() {
    return this->age;
}
char * Pig::getName() {
    return this->name;
}
void Pig::setAge(int age) {
    this->age = age;
}
void Pig::setName(char * name) {
    this->name = name;
}

void Pig::showPigInfo() const {

} // 常量指针常量 只读



// TODO ===============================  静态 和 友元 注意点 自己理解

// 实现 静态属性【不需要增加 static关键字】
int Pig::id = 878;

// 实现静态函数,【不需要增加 static关键字】
void Pig::changeTag(int age) {

}

// 友元的实现
// 友元特殊:不需要关键字,也不需要 对象:: ,只需要保证 函数名(参数)
void changeAge(Pig * pig, int age) {

}
关于友元类的思考与延伸:

Java中可以使用反射,获取到类中的私有属性。使用C++代码实现的话,可以直接使用友元类,获取累中的私有属性。 代码如下:

// ImageView 私有成员  可以通过Class来访问,但是Class操作的native C++代码

// ImageView 私有成员  你能访问它的私有成员吗 Class
#include <iostream>

using namespace std;

class ImageView {
private:
    int viewSize;
    friend class Class; // 声明友元类
};

// 实现友元类  Java每个类,都会有一个Class,此Class可以操作 ImageView私有成员
class Class {
public:
    ImageView imageView;

    void changeViewSize(int size) {
        imageView.viewSize = size;
    }

    int getViewSize() {
        return imageView.viewSize;
    }
};

int main() {
    Class mImageViewClass;

    mImageViewClass.changeViewSize(600);

    cout << mImageViewClass.getViewSize() << endl;

    return 0;
}

7.C++ 操作符重载

7.1 类外操作符重载
#include <iostream>

using namespace std;

// 类外运算符重载

class Point{
private:
    int x,y;
public:
    Point(int x, int y) : x(x),y(y) {}

    void setX(int x){
        this->x = x;
    }

    void setY(int y){
        this->y = y;
    }

    int getX(){
        return this->x;
    }

    int getY(){
        return this->y;
    }
};

// 类外运算符重载  外部是不能获取到内部私有成员的
Point operator + (Point point1, Point point2){
    int x = point1.getX() + point2.getX();
    int y = point1.getY() + point2.getY();
    Point p(x,y);
    return p;
}
int main() {
    Point p1(1000,2000);
    Point p2(3000,4000);
    Point p = p1 + p2;
    cout << p.getX() <<" , "<< p.getY() << endl;
    return 0;
}
7.2 类里运算符重载
// 类里操作符重载 + - i++ ++i <<  连续打印
#include <iostream>

using namespace std;
class Point{
private:
    int x,y;
public:
    Point(int x,int y):x(x),y(y){}
    void setX(int x){
        this->x = x;
    }

    void setY(int y){
        this->y = y;
    }

    int getX(){
        return this->x;
    }

    int getY(){
        return this->y;
    }

    // 类里操作符重载 第一种情况: 未使用const 关键字
    Point operator + (Point p){
        // this 指针指向当前对象
        int x = this->x + p.getX();
        int y = this->y + p.getY();
        return Point(x,y);
    }

    // 类里操作符重载 第二种情况: 使用const 关键字
    // const 关键字 只读 &性能的提高 如果增加了 & 引用,就是给这块内存空间取一个别名
    Point operator + (const Point &point){
        int x = this->x + point.x;
        int y = this->y + point.y;
        return Point(x,y);
    }

    Point operator - (const Point &point){
        int x = this->x - point.x;
        int y = this->y - point.y;
        return Point(x,y);
    }

    // ++对象
    void operator ++ (){
        this->x = this->x + 1;
        this->y = this->y + 1;
    }

    // 对象++
    void operator ++(int){
        this->x = this->x + 1;
        this->y = this->y +1;
    }

    // 输出运算符重载
    friend void operator << (ostream & _START,Point point){
        _START << "Point 输出 : x = " << point.x << "y = " << point.y << endl;
    }

    // 多重输出 返回ostream
    friend ostream & operator >> (ostream & _START,const Point &point){
        _START << "开始输出: x = " << point.x << " y = " << point.y << endl;
        return _START;
    }

    // 输入运算符重载  接收用户的输入 把输入的信息 给x y
    friend istream & operator >> (istream & _START, Point & point){
        _START >> point.x >> point.y;
        return _START;
    }

};

int main(){

    Point p1(1000,2000);
    Point p2(3000,4000);

    Point point = p2 + p1;

    cout << "+ x = " << point.getX() << ". y = " << point.getY() << endl;

    Point point1 = p2 - p1;

    cout << "- x = " << point1.getX() << ". y = " << point1.getY() << endl;

    Point point2(1000,2000);
    point2++;
    cout << point2.getX() << " --- " << point2.getY() << endl;
    ++point2;
    cout << point2.getX() << " --- " << point2.getY() << endl;

    // 输出
    cout << point2 ;

    // 换行
    cout << endl;

    cout >> point >> point1 >> point2 ;


    // cin输入
    Point point3(5000,6000);
    cin >> point3;
    cout << "你输入的是:" << point3.getX() << endl;
    cout << "你输入的是:" << point3.getY() << endl;

    return 0;
}
7.3 括号运算符
#include <iostream>

using namespace std;
// 写一个小容器 模拟容器
class ArrayClass{
private:
    // C++ 默认都是系统值
    int size = 0;  // 如果不赋值, size就是系统值 -13275 会出现后患无穷的问题
    int * arrayValue; // 数组存放int类型的很多值

public:
    void set(int index,int value){
        arrayValue[index] = value; // 这个[] 是系统的
        size += 1;
    }

    int getSize(){
        return this->size;
    }


    int operator[](int index){
        return arrayValue[index]; // 这个[] 是系统的
    }

};

void printArrayClass(ArrayClass aClass){
    cout << aClass.getSize() << endl;
    for(int i = 0; i < aClass.getSize();++i) {
        cout << aClass[i] << endl; // [] 是我们自己的符号重载
    }
}

int main(){
    ArrayClass arrayClass;
    arrayClass.set(0,1000);
    arrayClass.set(1,2000);
    arrayClass.set(2,3000);
    arrayClass.set(3,4000);
    arrayClass.set(4,5000);

    printArrayClass(arrayClass);

    return 0;
}

8. C++继承中的继承

8.1 单继承
// C++对象继承
#include <iostream>

using namespace std;
class Person{
public:
    char * name;
    int age;
public:
    Person(char * name,int age):name(name){
        this->age=age;
        cout << "Person 构造函数" << endl;
    }

    void print(){
        cout << this->name << "," << this->age << endl;
    }
};


// 继承
/*
 * 1. 默认是私有继承: 隐式代码 : private Person
 * 2. 私有继承: 在子类里面是可以访问父类的成员,但在类外不行
 * 3. 必须公开继承,才可以访问父类的成员
 */
class Student : public Person{
private:
    char * course;
public:
    Student(char * name,int age,char * course): Person(name,age),course(course){
        cout << "student 构造函数" << endl;
    }

    void test(){
        cout << name << endl;
        cout << age << endl;
        cout << course << endl;
        print();
    }
};

int main() {
    Student student("xx", 90, "Play");
    student.name = "YY";
    student.test();
    return 0;
}
8.2 多继承

C++的多继承,会导致二义性

// C++的多继承 导致二义性
#include <iostream>

using namespace std;
class BaseActivity1{
public:
    void onCreate(){
        cout << "BaseActivity1 OnCreate()" << endl;
    }

    void onStart(){
        cout << "BaseActivity1 onStart()" << endl;
    }

    void show(){
        cout << "BaseActivity1 show()" << endl;
    }

};

class BaseActivity2{
public:
    void onCreate(){
        cout << "BaseActivity2 OnCreate()" << endl;
    }

    void onStart(){
        cout << "BaseActivity2 onStart()" << endl;
    }

    void show(){
        cout << "BaseActivity2 show()" << endl;
    }

};

class BaseActivity3{
public:
    void onCreate(){
        cout << "BaseActivity3 OnCreate()" << endl;
    }

    void onStart(){
        cout << "BaseActivity3 onStart()" << endl;
    }

    void show(){
        cout << "BaseActivity3 show()" << endl;
    }

};

// 子类 继承 三个父类
class MainActivity1 : public BaseActivity1,public BaseActivity2,public BaseActivity3{
public:
    void onCreate() {
        cout << "MainActivity1 onCreate" << endl;
    }

    void onStart() {
        cout << "MainActivity1 onStart" << endl;
    }

    void showSonInfo() {
        cout << "MainActivity1 showSonInfo" << endl;
    }

    void show(){
        cout << "MainActivity1 show" << endl;
    }


};

int main(){
    MainActivity1 mainActivity1;
    mainActivity1.onCreate();
    mainActivity1.onStart();
    mainActivity1.showSonInfo();


    // 这里会导致二义性 不知道去哪个父类里面去找show方法
//    mainActivity1.show();


    // 解决方式1 : 明确指定父类
    mainActivity1.BaseActivity1::show();
    mainActivity1.BaseActivity2::show();
    mainActivity1.BaseActivity3::show();

    //解决方案二:子类上 重写父类的show()
    mainActivity1.show();

    return 0;
}

二义性的解决方案:

// 二义性
#include <iostream>

using namespace std;

class Object{
public:
    int number;
};

class BaseActivity1 : public Object{

};

class BaseActivity2 : public Object{

};

class Son : public BaseActivity1,public BaseActivity2{
public:
    int number;
};

int main(){
    Son son;

    // 第一种解决二义性的方案:明确指定
    son.BaseActivity1 :: number = 1000;
    son.BaseActivity2 :: number = 1000;

    // 第二种解决方法:在类中定义同名成员 覆盖掉父类的相关成员
    son.number = 2000;

    // 第三种解决方案 【虚基类】 属于 虚继承的范畴

    return 0;
}

// 二义性
#include <iostream>

using namespace std;

class Object{
public:
    int number;
};

class BaseActivity1 : public Object{

};

class BaseActivity2 : public Object{

};

class Son : public BaseActivity1,public BaseActivity2{
public:
    int number;
};

int main(){
    Son son;

    // 第一种解决二义性的方案:明确指定
    son.BaseActivity1 :: number = 1000;
    son.BaseActivity2 :: number = 1000;

    // 第二种解决方法:在类中定义同名成员 覆盖掉父类的相关成员
    son.number = 2000;

    // 第三种解决方案 【虚基类】 属于 虚继承的范畴

    return 0;
}
8.3 虚基类
// 虚基类 属于虚继承的范畴  虚基类 另外制造了一份 变量和方法 让子类去继承
#include <iostream>

using namespace std;

class Object{
public:
    int number;
    void show(){
        cout << "Object show run..." << endl;
    }
};

// 父类1
class BaseActivity1 :virtual public Object{
//public:
//    int number;
};

// 父类2
class BaseActivity2 : virtual public Object{
//public:
//    int number;
};

// 子类
class Son : public BaseActivity1,public BaseActivity2{

};

int main(){
    Object object;
    BaseActivity1 baseActivity1;
    BaseActivity2 baseActivity2;
    Son son;

    object.number = 100;
    baseActivity1.number = 200;
    baseActivity2.number = 300;
    son.number = 400;

    object.show();
    baseActivity1.show();
    baseActivity2.show();
    son.show();

    cout << object.number << endl;
    cout << baseActivity1.number << endl;
    cout << baseActivity2.number << endl;
    cout << son.number << endl;
    return 0;
}
8.4 源码中属性初始化方法
#include <iostream>
using namespace std;

class Person{
protected:
    string name;
    int age;
public :
    Person(string name,int age) : name(name),age(age){}
};

class Course{
private:
    string name;
public:
    Course(string name) : name(name){}
};

class Student : public Person{
private:
    Course course; // 对象成员
public:
    Student(string name,int age,Course course1,string courseName) : Person(name,age),course(courseName){

    }
};

int main(){
    Course course("C++");
    Student student("Name",35,course,"CourseName");
    return 0;
}
8.5 虚继承
#include <iostream>
using namespace std;
// 祖父类
class Object{
public:
    string info;
};

// 父类
class Base1 : virtual public Object{};
class Base2 : virtual public Object{};

// 子类
class Main1 : public Base1,public Base2{};

int main(){
    Object object;
    Base1 base1;
    Base2 base2;
    Main1 main1;

    object.info = "A";
    base1.info = "B";
    base2.info = "C";
    main1.info = "D";

    cout << object.info << endl;
    cout << base1.info << endl;
    cout << base2.info << endl;
    cout << main1.info << endl;

    exit(0);
}

原理图:

截图.png

9.静态多态

编译期已经决定,调用哪个函数了 : 重载

#include <iostream>

using namespace std;

void add(int number1, int number2) {
    cout << number1 + number2 << endl;
}

void add(float number1, float number2) {
    cout << number1 + number2 << endl;
}

void add(double number1, double number2) {
    cout << number1 + number2 << endl;
}

int main() {
    add(10000, 10000);
    add(1.9f, 2.8f);
    add(545.4, 654.54);

    return 0;
}

10.纯虚函数

C++的纯虚函数 就相当于Java的抽象类

// 纯虚函数  C++的纯虚函数 就相当于Java的抽象类
#include <iostream>

using namespace std;

class BaseActivity1{
private:
    void setContentView(string layoutId){
        cout << layoutId << endl;
    }


public:
    void onCreate(){
        setContentView(getLayoutID());

        initView();
        initData();
        initListener();
    }

    // 纯虚函数是必须继承的 (如果子类没有重写纯虚函数,子类就是抽象类)虚函数是不是不必须的

    // 纯虚函数
//    virtual string getLayoutID() ; // 没有赋值的 是虚函数
    virtual string getLayoutID() = 0; // 赋值的是纯虚函数
    virtual void initView() = 0;
    virtual void initListener() = 0;
    virtual void initData() = 0;

};

class MainActivity : public BaseActivity1{
    string getLayoutID(){
        return " MainActivity ";
    }

    void initView(){}

    void initListener(){}

    void initData(){}
};

class HomeActivity : public BaseActivity1{
    string getLayoutID(){
        return " HomeActivity ";
    }

    void initView(){
    }

    void initListener(){
    }

    void initData(){
    }
};

class LoginActivity : public BaseActivity1{
    string getLayoutID(){
        return " LoginActivity ";
    }

    void initView(){
    }

    void initListener(){
    }

    void initData(){
    }
};

int main(){
    MainActivity mainActivity;
    return 0;
}

11.全纯虚函数

相当于Java的接口

// 全纯虚函数  (相当于Java中的接口)
#include <iostream>

using namespace std;

class Student{
    int _id;
    string name;
    int age;
};

// 此类所有的函数, 都是纯虚函数 相当于Java的接口
class IStudent_DB{
    virtual void insertStudent(Student student) = 0;
    virtual void deleteStudent(int _id) = 0;
    virtual void updateStudent(int _id,Student student) = 0;
    virtual void queryByStudent(Student student) = 0;
};

class IStudent_Impl : IStudent_DB{
public:
    void insertStudent(Student student){

    }

    void deleteStudent(int _id){

    }

    void updateStudent(int _id,Student student){

    }

    void queryByStudent(Student student){

    }
};

class IStudent_Impl2 : IStudent_DB{
public:
    void insertStudent(Student student){

    }

    void deleteStudent(int _id){

    }

    void updateStudent(int _id,Student student){

    }

    void queryByStudent(Student student){

    }
};

class IStudent_Impl3 : IStudent_DB{
public:
    void insertStudent(Student student){

    }

    void deleteStudent(int _id){

    }

    void updateStudent(int _id,Student student){

    }

    void queryByStudent(Student student){

    }
};

int main(){
    IStudent_Impl iStudent1;
    IStudent_Impl2 iStudentImpl2;
    IStudent_Impl3 iStudentImpl3;

    cout << "Success" << endl;

    return 0;
}

12.回调

// 回调
#include <iostream>

using namespace std;

class SuccessBean{
public:
    string userName;
    string userPwd;

    SuccessBean(string username,string userpwd) : userName(username),userPwd(userpwd){

    }
};

class ILoginResponse{
public:
    virtual void loginSuccess(int code,string message,SuccessBean successBean) = 0;
    virtual void loginError(int code,string message) = 0;
};

void loginAction(string name,string pwd,ILoginResponse & loginResponse){
    if(name.empty() || pwd.empty()){
        cout << "用户名或密码为空" << endl;
        return;
    }

    if("Kim" == name && "123" == pwd){
        loginResponse.loginSuccess(200,"登录成功", SuccessBean(name,"恭喜进入"));
    }else{
        loginResponse.loginError(400,"登录失败");
    }
}

class ILoginResponseImpl : public ILoginResponse{
public:
    void loginSuccess(int code,string msg,SuccessBean successBean){
        cout << "恭喜登录成功!"
             << ",code : "
             << code
             << ",msg : "
             << msg
             << ",successBean : "
             << successBean.userName
             << ","
             << successBean.userPwd
             << endl;
    }

    void loginError(int code,string msg){
        cout << "登录失败," << "code : " << code << ",message : " << msg << endl;
    }
};

int main(){
    string username;
    cout << "请输入用户名 : " <<endl;
    cin >> username;


    string pwd;
    cout << "请输入密码:" << endl;
    cin >> pwd;

    ILoginResponseImpl iLoginResponse;
    loginAction(username,pwd,iLoginResponse);
    return 0;
}

12.模板函数

相当于Java的泛型

// 模板函数 相当于Java的泛型
#include <iostream>
using namespace std;
//void add(int number1,int number2){
//    cout << number1 + number2 << endl;
//}
//
//void add(float number1,float number2){
//    cout << number1 + number2 << endl;
//}
//
//void add(double number1,double number2){
//    cout << number1 + number2 << endl;
//}

// 模板函数 == Java泛型
template <typename TT>
void add(TT n1,TT n2){
    cout << "模板函数:" << n1 + n2 <<endl;
}

int main(){
    add(290,10);
    add(2.0f,3.0f);
    add(2.13,3.45);
    add<string>("AAA","BBB");
    return 0;
}

13.继承关系的时候,构造函数和析构函数的顺序问题

// 构造函数和析构函数的顺序问题
#include <iostream>

using namespace std;
class Person{
public:
    string name;
    Person(string name) : name(name) {
        cout << "Person 构造函数" << endl;
    }

    ~Person(){
        cout << "Person 析构函数" << endl;
    }

    virtual void test(){
        cout << "父 test..." << endl;
    }
};

class Student : public Person{
public:
    string name;
    Student(string name) : Person(name){
        cout << "Student 构造函数" << endl;
    }

    ~Student(){
        cout << "Student 析构函数" << endl;
    }

    void test(){
        cout << "子 test..." << endl;
    }

};

int main(){
    Student student("Kim");
    student.test();
    return 0;
}

打印结果:

Person 构造函数 
Student 构造函数
子 test...
Student 析构函数 
Person 析构函数

14. C++ 容器

14.1 Vector

Vector内部是封装了动态大小数组作为容器,能够存放任意的动态数组。

/**
 * STL  C++的标准模板库
 * STL Standard Template Library
 * C++ 的 vector 向量 容器 (内部 : 封装动态大小数组作为容器,能够存放任意的动态数组)
 */

#include <iostream>
#include <vector>  // 引入vector 容器支持

using namespace std;

int main(){
    vector<int> vector1;
    vector<int> vector2(10); // 指定10个空间大小
    vector<int> vector3(10,0); // 有了10个值,每个值都是0
    vector<int> vector4;

    // 插入数据 每次都插入到第一个
    vector4.insert(vector4.begin(),40);
    vector4.insert(vector4.begin(),80);
    vector4.insert(vector4.begin(),100);
    vector4.insert(vector4.begin(),150);
    vector4.insert(vector4.begin(),200);

    // 第一个
    cout << " 修改前:vector4.front():" << vector4.front() << endl;
    vector4.front() = 99; // 默认修改第一个
    cout << " 修改后:vector4.front():" << vector4.front() << endl;

    // 最后一个
    cout << "修改前 :vector4.back() " << vector4.back() << endl;
    vector4.back() = 88;
    cout << "修改后:vector4.back() " << vector4.back() << endl;

    vector4.erase(vector4.begin()); // 移除第一个元素

    // 循环打印 默认是从大到小输出
    for(int i = 0; i < vector4.size(); i++){
        cout << "item : " << vector4[i] << endl;
    }

    // 迭代器 循环遍历
//    for(vector<int>::iterator iteratorVar = vector4.begin() ; iteratorVar != vector4.end(); iteratorVar ++){
//        cout << "迭代器:" << *iteratorVar << endl;
//    }

    for(auto iteratorVar = vector4.begin(); iteratorVar != vector4.end(); iteratorVar ++){
        cout << "迭代器:" << *iteratorVar << endl;
    }

    return 0;
}
14.2 Stack 栈

先进后出,后进先出,手枪子弹上膛的一个思路。

// stack  栈  后进先出 先进后出
#include <iostream>
#include <stack>
using namespace std;

int main(){
    stack<int> stackVar;

    // 压栈 stack无法指定位置去压栈
    stackVar.push(30);
    stackVar.push(60);
    stackVar.push(90);

    // 循环遍历stack 是行不通的 因为stack内部没有重载[]运算符
    // stack中也没有迭代器

    // 所以要循环stack 就需要把元素都弹栈  这种方式是可以的 但是没必要 全部元素都弹完了
    while (!stackVar.empty()){
        // 获得栈顶元素
        int top =  stackVar.top();
        cout << "获取栈顶元素 :" << top << endl;
        stackVar.pop(); // 把栈顶元素弹出去
    }
    return 0;
}
14.3 queue 队列
// queue 队列使用 内部: 链表 数组  先进先出
#include <iostream>
#include <queue>

using namespace std;
int main(){
    queue<int> queueVar;

    queueVar.push(20);
    queueVar.push(40);
    queueVar.push(60);

    // FIFO 原则 第一个元素就是20
    cout << "修改前:queueVar.front() " << queueVar.front() << endl;
    queueVar.front() = 88;
    cout << "修改后:queueVar.front() " << queueVar.front() << endl;

    // 最后一个 最后一个元素是60
    cout << "修改前:queueVar.back() " << queueVar.back() << endl;
    queueVar.back() = 99;
    cout << "修改后:queueVar.back() " << queueVar.back() << endl;

    while (!queueVar.empty()){
        cout << " 第一次遍历 : " << queueVar.front() << endl;
        queueVar.pop(); // 把前面的元素给消费掉
    }

    while (!queueVar.empty()){
        // 没有元素了
        cout << " 第二次遍历 : " << queueVar.front() << endl;
        queueVar.pop(); // 把前面的元素给消费掉
    }
    return 0;
}
14.4 优先级队列 : priority_queue

增加了从大到小或者从小到大排序

// 优先级队列
#include <iostream>
#include <queue>

using namespace std;

int main(){
    // 优先级队列 默认做了从大到小排序
    /**
      *  对于priorityQueue来说, C++其实默认的隐式代码是:
      *  priority_queue<int, vector<int>, less<int>> priorityQueue;
      *  less ==》源码中: less<int> return _x < _y 上一个元素和当前元素比较 返回true 或者 false  从大到小排序
      *
      *  greater ==> 源码中: return _x > _y  从小到大排序
      *
      */

    // 从大到小排序
//    priority_queue<int> priorityQueue;
//    priority_queue<int, vector<int>, less<int>> priorityQueue;

    // 从小到大排序
    priority_queue<int,vector<int>,greater<int>> priorityQueue;

    priorityQueue.push(10);
    priorityQueue.push(50);
    priorityQueue.push(70);
    priorityQueue.push(20);
    priorityQueue.push(40);
    priorityQueue.push(30);


    while (!priorityQueue.empty()){
        cout << "while : " << priorityQueue.top() << endl;
        priorityQueue.pop();
    }

    return 0;
}
14.5 List

List的内部是一个链表结构

// List 内部 采用链表
#include <iostream>
#include <list>

using namespace std;
int main(){
    list<int> listVar;

    // 插入数据
    listVar.push_front(50);
    listVar.push_back(100);
    listVar.insert(listVar.begin(),70);
    listVar.insert(listVar.end(),80);

    // 修改操作
    listVar.front() = 85;
    listVar.back() = 95;

    // 删除操作
    listVar.erase(listVar.begin());
    listVar.erase(listVar.end());

    for(list<int> :: iterator it = listVar.begin() ; it != listVar.end(); it++){
        cout << *it <<endl;
    }

    return 0;
}
14.6 Set容器

Set容器内部是一个红黑树结构 会对存入的数据排序,但是绝对不允许相同

// set容器 内部: 红黑树结构 会对存入的数据排序,但是绝对不允许相同
#include <iostream>
#include <set>

using namespace std;

int main(){
    // 默认情况下 从小到大
    set<int,less<int>> setVar;

    // 添加参数 不需要用迭代器 也不需要指定位置
    setVar.insert(1);
    setVar.insert(3);
    setVar.insert(2);
    setVar.insert(4);

    pair<set<int,less<int>>::iterator ,bool> res = setVar.insert(8);

    bool insert_success = res.second;
    if(insert_success){
        cout << "插入成功!" << endl;

        for(;res.first != setVar.end() ; res.first ++){
            cout << *res.first << endl;
        }
    }else{
        cout << "插入失败!" << endl;
    }

    // 遍历
    for(auto it = setVar.begin(); it != setVar.end(); it ++){
        cout << *it << endl;
    }
    return 0;
}
14.7 谓词
// 谓词 设计对象的排序
#include <iostream>
#include <set>

using namespace std;

class Person{
public:
    string name;
    int id;
    Person(string name,int id) : name(name),id(id){}
};

struct compareAction2{
public:
    bool operator()(const Person &_x,Person &_y){
        return _x.id < _y.id;
    }
};

int main(){
    // 在这里使用自定义的谓词
    set<Person,compareAction2> setVar;

    Person p1("A",1);
    Person p2("B",2);
    Person p3("C",3);

    setVar.insert(p1);
    setVar.insert(p2);
    setVar.insert(p3);

    for(set<Person> :: iterator it = setVar.begin();it != setVar.end(); it++){
        cout << it->name.c_str() << endl;
    }

    return 0;
}
14.8 Map

Map会对key进行排序,并且key不能重复

// Map的学习  : Map会对key进行排序,并且key不能重复

#include <iostream>
#include <map>

using namespace std;
int main(){
    map<int,string> mapVar;

    // 插入数据 三种方式
    // 第一种方式:
    mapVar.insert(pair<int,string>(1,"一"));
    // 第二种方式
    mapVar.insert(make_pair(2,"二"));
    // 第三种方式
    mapVar.insert(map<int,string>::value_type(3,"三"));
    // 第四种方式 覆盖修改时使用
    mapVar[4] = "4";
    mapVar[4] = "肆";


    // 循环打印 迭代器
    for(map<int,string>::iterator it = mapVar.begin();it != mapVar.end(); it++){
        cout << it->first << " , " << it->second.c_str() << endl;
    }

    // 怎么判断插入成功了没  insert 的返回值 :std::pair<iterator, bool>
    std::pair<map<int,string>::iterator , bool> pair =  mapVar.insert(map<int,string>::value_type(4,"六"));
    if(pair.second){
        cout << "插入成功!" << endl;
    }else{
        cout << "插入失败!" << endl;
    }

    // 插入后的数据
    for(pair.first == mapVar.begin();pair.first != mapVar.end();pair.first ++){
        cout << pair.first->first << " , " << pair.first->second << endl;
    }


    // find的返回值 : iterator
    map<int,string>:: iterator findResult = mapVar.find(3);
    if(findResult != mapVar.end()){
        cout << "找到了" << findResult->first << " , " << findResult->second.c_str() << endl;
    }else{
        cout << "没找到 " << endl;
    }

    return 0;
}
14.9 multimap容器

multimap容器:1.key可以重复, 2.key重复的数据可以分组, 3.key会排序, 4.value不会排序

//multimap : 1.key可以重复, 2.key重复的数据可以分组,  3.key会排序,  4.value不会排序
#include <iostream>
#include <map>

using namespace std;
int main(){
    multimap<int,string> multimapVar;

    multimapVar.insert(make_pair(10,"一"));
    multimapVar.insert(make_pair(10,"二"));
    multimapVar.insert(make_pair(10,"三"));
    multimapVar.insert(make_pair(10,"四"));
    multimapVar.insert(make_pair(10,"五"));

    multimapVar.insert(make_pair(30,"六"));
    multimapVar.insert(make_pair(30,"七"));
    multimapVar.insert(make_pair(30,"八"));
    multimapVar.insert(make_pair(30,"九"));
    multimapVar.insert(make_pair(30,"十"));

    multimapVar.insert(make_pair(20,"六"));
    multimapVar.insert(make_pair(20,"七"));
    multimapVar.insert(make_pair(20,"八"));
    multimapVar.insert(make_pair(20,"九"));
    multimapVar.insert(make_pair(20,"十"));

    for(auto it = multimapVar.begin() ; it != multimapVar.end() ; it ++){
        cout << it->first << " , " << it->second << endl;
    }
    cout << endl;

    // 输入查询
    int result;
    cout << "请输入你要查询的key,为int类型" << endl;
    cin >> result;

    multimap<int,string>::iterator iterator = multimapVar.find(result);
    while (iterator != multimapVar.end()){
        cout << iterator->first << "," << iterator->second << endl;

        //
        iterator++;
        if(iterator->first != result){
            break; // 循环结束
        }

        if(iterator == multimapVar.end()){
            break; // 循环结束
        }
    }
    return 0;
}

15. 谓词一

谓词就是仿函数

// 谓词 ==  仿函数
#include <iostream>
#include <algorithm>

using namespace std;

class ComPareObject{
public:
    // 根据参数的个数 分为 空谓词 一元谓词 二元谓词 三元谓词
    void operator()(){
        cout << "仿函数" << endl;
    }
};

void fun(){
    cout << "普通函数" << endl;
}

int main(){
    ComPareObject fun1;

    fun1(); // 使用仿函数 非常像函数的调用

    fun(); // 普通函数的调用

    return 0;
}

16. 谓词二

#include <iostream>
#include <set>
#include <algorithm> // 算法包

using namespace std;

class showActionObj{
public:
    void operator()(int content){
        cout << "自定义仿函数" << content << endl;
    }
};

// 普通函数
void showAction(int content){
    cout << "普通函数" << content << endl;
}

int main(){
    set<int> setVar;

    setVar.insert(10);
    setVar.insert(20);
    setVar.insert(30);
    setVar.insert(40);
    setVar.insert(50);
/**
 * for_each 方法的三个参数 :
 *   @param  __first  An input iterator. 迭代器  开始的位置
 *  @param  __last   An input iterator.  迭代器  结束的位置
 *  @param  __f      A unary function object.   Function  函数 : 回调函数或者仿函数  在for_each的源码中,会把
 */

    // TODO for_each 的源码:
//    template<typename _InputIterator, typename _Function>
//    _Function
//    for_each(_InputIterator __first, _InputIterator __last, _Function __f)
//    {
//        // concept requirements
//        __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
//        __glibcxx_requires_valid_range(__first, __last);
//        for (; __first != __last; ++__first)

    // 在这个位置,会把_first的值传递给 __f 
//            __f(*__first);
//        return __f; // N.B. [alg.foreach] says std::move(f) but it's redundant.
//    }
    for_each(setVar.begin(),setVar.end(), showActionObj());

    return 0;
}

17. 谓词三

// 回调函数 和 仿函数
#include <iostream>
#include <set>
#include <algorithm>

using namespace std;

// 回调函数 也叫一元谓词
void showAction(int _first){
    cout << "一元谓词" << endl;
}

// 仿函数 可扩展性更强
class showActionObj{
public:
    int count;
    void _count(){
        cout << "第几次打印" << count << endl;
    }
    void operator()(int content){
        cout << "仿函数" << content << endl;
        count ++;
    }
};

int main(){
    set<int> setVar;

    setVar.insert(10);
    setVar.insert(20);
    setVar.insert(30);
    setVar.insert(40);
    setVar.insert(50);
    setVar.insert(60);

    // 循环打印 第三个参数是一个 _Function __f
//    for_each(setVar.begin(),setVar.end(), showAction);

    // 这传样写 没办法打印出count  因为这个入的showActionObj是新的副本,
    // 我们外面的是showActionObj的旧地址
//    for_each(setVar.begin(),setVar.end(),showActionObj());

    // 改进:
    showActionObj s;
    s = for_each(setVar.begin(),setVar.end(),s);
    s._count();

    return 0;
}

18.模仿源码,写仿函数

// 模仿源码 写仿函数
#include <iostream>
#include <set>

using namespace std;

// TODO less源码
//template<typename _Tp>
//struct less : public binary_function<_Tp, _Tp, bool>
//{
//    _GLIBCXX14_CONSTEXPR
//    bool
//    operator()(const _Tp& __x, const _Tp& __y) const
//    { return __x < __y; }
//};

// 根据less源码 进行仿写
class CompareObject{
public:
    bool operator()(const string & _x,const string & _y) const{
        return _x > _y;
    }
};

int main(){


    /**
     * template<typename _Key, typename _Compare = std::less<_Key>,
      typename _Alloc = std::allocator<_Key> >

        源码中,第二个参数 如果没有 就使用内置的仿函数less  可以自定义仿函数  自定义可以根据less的格式去写
     */

    set<string,CompareObject> setVar; // 倒序
    // set<string> setVar;  // 正序
    setVar.insert(setVar.begin(),"AAAAA");
    setVar.insert(setVar.begin(),"BBBBB");
    setVar.insert(setVar.begin(),"CCCCC");
    setVar.insert(setVar.begin(),"DDDDD");
    setVar.insert(setVar.begin(),"EEEEE");
    setVar.insert(setVar.begin(),"FFFFF");

    // 循环  打印出来是正序
    for (set<string> :: iterator it = setVar.begin(); it != setVar.end() ; it++) {
        cout << "循环Item : " <<  *it << "\t";  // 不换行
    }
    return 0;
}

19.对象存入容器后,对象的生命周期状态

// 对象存入容器后,对象的生命周期状态
#include <iostream>
#include <set> // set 存入对象会崩溃,因为set会自动排序,对象无法排序,所以崩溃,解决办法:自定义仿函数
#include <vector>

using namespace std;
class Person{
private:
    string name;
public:
    Person(string name):name(name){}

    void setName(string name){
        this->name = name;
    }

    string getName(){
        return this->name;
    }

    // 拷贝构造函数
    Person(const Person & person){
        this->name = person.name; // 浅拷贝
        cout << "Person的拷贝构造函数执行了...." << endl;
    }

    ~Person(){
        cout << "Person的析构函数执行了...." << endl;
    }
};

int main(){
    vector<Person> vectorVar;
    // main函数弹栈时,析构函数执行一次
    Person person("AA");

    // 外面的person是旧地址,insert参数中的person是新地址 (这里调用拷贝构造函数一次)
    // insert函数弹栈时,person的析构函数执行一次
    vectorVar.insert(vectorVar.begin(),person);

    person.setName("BB");

    // main函数弹栈时,newPerson的析构函数被执行一次
    Person newPerson = vectorVar.front(); // 这里得到的Person是旧地址,外面的newPerson是新地址 (这里调用拷贝构造函数一次)
    cout << "newPerson : " << newPerson.getName() << endl;
    return 0;
} // 执行完毕 main函数弹栈

// 拷贝构造函数 运行两次  析构函数 运行三次

20.预定义函数

// C++的预定义函数
#include <iostream>
#include <algorithm>

using namespace std;

int main(){

    // C++已经提供了 预定义函数  plus,minus,multiplies,divides,modulus ...

    plus<int> add_fun;
    int r = add_fun(1,2);
    cout << r << endl;

    plus<string> add_fun2;
    string r2 = add_fun2("AAA","BBB");
    cout << r2 << endl;

    plus<float> add_fun3;
    float r3 = add_fun3(454.45f,234.9f);
    cout << r3 << endl;

    return 0;
}

21. 手写预定义函数

// 手写预定义函数 根据plus源码 模仿预定义函数 plus
#include <iostream>
#include <algorithm>

using namespace std;

// plus的源码:
// template<typename _Tp>
// struct plus : public binary_function<_Tp, _Tp, _Tp>
// {
//    _GLIBCXX14_CONSTEXPR
//    _Tp
//    operator()(const _Tp& __x, const _Tp& __y) const
//    { return __x + __y; }
// };

// binary_function 源码:
template<typename _Arg1, typename _Arg2, typename _Result>
struct binary_function
{
    /// @c first_argument_type is the type of the first argument
    typedef _Arg1  first_argument_type;

    /// @c second_argument_type is the type of the second argument
    typedef _Arg2  second_argument_type;

    /// @c result_type is the return type
    typedef _Result    result_type;
};

template<typename T>
struct plus_d /*: public binary_function<T,T,T> */{
    T operator()(const T & x , const T & y){
        return x + y;
    }
};

int main(){
    plus<int>  add_fun;
    add_fun(1,2);

    plus_d<int> add_d;
    int r = add_d(1,2);
    cout << r << endl;

    return 0;
}

二、C++高级之算法包

1. 函数适配器 : bind2nd bind1st

// 1. 函数适配器
#include <iostream>
#include <set>
#include <algorithm>

using namespace std;

int main(){
    cout << "算法包" << endl;

    set<string,less<string>> setVar;
    setVar.insert("AAAA");
    setVar.insert("BBBB");
    setVar.insert("CCCC");

    for(set<string> :: iterator it = setVar.begin(); it != setVar.end(); it++){
        cout << *it << endl;
    }

    // TODO 学习一下find_if的源码:

//    template<typename _InputIterator, typename _Predicate>
//    inline _InputIterator // 返回值是一个迭代器
//    find_if(_InputIterator __first,  // 迭代器的初始位置
//            _InputIterator __last,   // 迭代器的结束位置
//            _Predicate __pred) // 规则
//    {
//        // concept requirements
//        __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
//        __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
//                                    typename iterator_traits<_InputIterator>::value_type>)
//        __glibcxx_requires_valid_range(__first, __last);
//
//        return std::__find_if(__first, __last,
//                              __gnu_cxx::__ops::__pred_iter(__pred));
//    }

    set<string,less<string>>::iterator iterator = find_if(setVar.begin(), setVar.end(), bind1st(equal_to<string>(),"CCCC"));

    if(iterator != setVar.end()){
        cout << "查找到了" << endl;
    }else{
        cout << "没有查找到" << endl;
    }
}

2. 算法包里的算法

2.1 for_each 遍历操作
// for_each 算法包里面的遍历
#include <iostream>
#include <vector>
#include <algorithm>


using namespace std;

class _F{
public:
    void operator()(int _first){
        cout << " : "<< _first << endl;
    }
};
int main() {
    vector<int> vectorVar;
    vectorVar.insert(vectorVar.begin(),10000);
    vectorVar.insert(vectorVar.begin(),20000);
    vectorVar.insert(vectorVar.begin(),30000);
    vectorVar.insert(vectorVar.begin(),40000);


    // TODO for_each 源码  
    // 参数 : _InputIterator __first,  开始位置
    //        _InputIterator __last,   结束位置
    //        _Function __f   算法规则

//    template<typename _InputIterator, typename _Function>
//    _Function
//    for_each(_InputIterator __first, _InputIterator __last, _Function __f)
//    {
//        // concept requirements
//        __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
//        __glibcxx_requires_valid_range(__first, __last);
//        for (; __first != __last; ++__first)
//            __f(*__first);
//        return __f; // N.B. [alg.foreach] says std::move(f) but it's redundant.
//    }
    for_each(vectorVar.begin(),vectorVar.end(),_F());

    return 0;
}
2.2 transform 变化操作
// transform 算法包里面的 变化操作
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class _unary_op{
public:
    int operator()(const int _frist){
        return _frist +9 ; // 变化 : 每个元素 + 9
    }
};

int main(){
    vector<int> vectorVar;
    vectorVar.insert(vectorVar.begin(),10000);
    vectorVar.insert(vectorVar.begin(),20000);
    vectorVar.insert(vectorVar.begin(),30000);
    vectorVar.insert(vectorVar.begin(),40000);

    // 参数:_InputIterator __first, 开始位置
    //      _InputIterator __last,  结束位置
    //       _OutputIterator __result, 迭代器result
    //       _UnaryOperation __unary_op 变化规则  每个数都+9
    transform(vectorVar.begin(),vectorVar.end(),vectorVar.begin(),_unary_op());
    for(auto it = vectorVar.begin();it != vectorVar.end(); it++){
        cout << "transform 1 " << *it << endl;
    }

    cout << endl;

    // TODO 第二种方式 定义一个新的vector接收
    vector<int> vectorResult ;
    vectorResult.resize(vectorVar.size()); // 定义vectorResult的大小
    transform(vectorVar.begin(),vectorVar.end(),vectorResult.begin(),_unary_op());
    for (auto it = vectorResult.begin(); it != vectorResult.end()  ; it ++) {
        cout << "transform 2 " << *it << endl;
    }
    return 0;
}
2.3 查找 find 和 find_if
// TODO 查找 find 和 find_if  算法包里的查找元素
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// TODO 2 find_if 需要自定义仿函数
class __pred{
public:
    int number;
    // 构造方法
    __pred(int number):number(number){}
    bool operator()(const int value){
        return number == value;
    }
};

int main(){
    vector<int> vectorVar;
    vectorVar.insert(vectorVar.begin(),10000);
    vectorVar.insert(vectorVar.begin(),20000);
    vectorVar.insert(vectorVar.begin(),30000);
    vectorVar.insert(vectorVar.begin(),40000);


    // TODO find的源码 : 就是对find_if的封装
//    template<typename _InputIterator, typename _Tp>
//    inline _InputIterator
//    find(_InputIterator __first,  // 开始位置
//         _InputIterator __last,   // 结束位置
//         const _Tp& __val)        // 需要查找的元素
//    {
//        // concept requirements
//        __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
//        __glibcxx_function_requires(_EqualOpConcept<
//                                    typename iterator_traits<_InputIterator>::value_type, _Tp>)
//        __glibcxx_requires_valid_range(__first, __last);
    // 对find_if的封装
//        return std::__find_if(__first, __last,
//                              __gnu_cxx::__ops::__iter_equals_val(__val));
//    }

// TODO 方式一 : find 没有自定义仿函数
//    auto it = find(vectorVar.begin(),vectorVar.end(),500);


    // TODO find_if的源码
//    find_if(_InputIterator __first,  // 开始位置
//            _InputIterator __last,   // 结束位置
//            _Predicate __pred)       // 自定义仿函数
//    {
//        .... 监测工作而已
//        return std::__find_if(__first, __last,
//                              __gnu_cxx::__ops::__pred_iter(__pred));
//    }

// TODO 方式二 : find_if 有自定义仿函数 __pred
    auto it = find_if(vectorVar.begin(),vectorVar.end(), __pred(30000));
    if(it != vectorVar.end()){
        cout << "查找到了!" <<endl;
    }else{
        cout << "没有找到" << endl;
    }
    return 0;
}
2.4 统计元素个数 count count_if
//TODO  算法包中的 统计元素个数 count count_if
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// TODO count 没有自定义仿函数
int main(){
    vector<int> vectorVar;
    vectorVar.insert(vectorVar.begin(),1);
    vectorVar.insert(vectorVar.begin(),2);
    vectorVar.insert(vectorVar.begin(),3);
    vectorVar.insert(vectorVar.begin(),4);
    vectorVar.insert(vectorVar.begin(),5);
    vectorVar.insert(vectorVar.begin(),1);
    vectorVar.insert(vectorVar.begin(),2);
    vectorVar.insert(vectorVar.begin(),3);
    vectorVar.insert(vectorVar.begin(),4);
    vectorVar.insert(vectorVar.begin(),5);

    int number = count(vectorVar.begin(),vectorVar.end(),2);
    cout << "等于2的个数是:" << number << endl;

    // TODO count_if
    number = count_if(vectorVar.begin(),vectorVar.end(), bind2nd(less<int>(),2));  // < 2 的个数
    cout << "小于2的个数是:" << number << endl;

    number = count_if(vectorVar.begin(),vectorVar.end(), bind2nd(greater<int>(),2)); // > 2 的个数
    cout << "大于2的个数是:" << number << endl;

    number = count_if(vectorVar.begin(),vectorVar.end(), bind2nd(equal_to<int>(),2)); // == 2 的个数
    cout << "等于2的个数是:" << number << endl;

    return 0;
}
2.5 合并 merge
// 算法包里的 合并 merge
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main(){
    vector<int> vectorVar;
    vectorVar.push_back(10);
    vectorVar.push_back(20);
    vectorVar.push_back(30);
    vectorVar.push_back(40);
    vectorVar.push_back(50);

    vector<int> vectorVar1;
    vectorVar1.push_back(60);
    vectorVar1.push_back(70);
    vectorVar1.push_back(80);
    vectorVar1.push_back(90);
    vectorVar1.push_back(100);

    // 合并成一个容器
    vector<int> vectorResult;
    vectorResult.resize(vectorVar.size() + vectorVar1.size());

    merge(vectorVar.begin(),vectorVar.end(),vectorVar1.begin(),vectorVar1.end(),vectorResult.begin());
    for(auto it = vectorResult.begin(); it != vectorResult.end() ; it++){
        cout << *it << endl;
    }

    return 0;
}


// TODO merge 的源码
// ....
//merge(_InputIterator1 __first1, _InputIterator1 __last1,
//      _InputIterator2 __first2, _InputIterator2 __last2,
//      _OutputIterator __result)
//{
//    ....
//    return _GLIBCXX_STD_A::__merge(__first1, __last1,
//                                   __first2, __last2, __result,
//                                   __gnu_cxx::__ops::__iter_less_iter());
//}


// TODO 点进:__merge
//__merge(_InputIterator1 __first1, _InputIterator1 __last1,
//        _InputIterator2 __first2, _InputIterator2 __last2,
//        _OutputIterator __result, _Compare __comp)
//{
// 做合并算法 处理的工作
//    while (__first1 != __last1 && __first2 != __last2)
//    {
//        if (__comp(__first2, __first1))
//        {
//            *__result = *__first2;
//            ++__first2;
//        }
//        else
//        {
//            *__result = *__first1;
//            ++__first1;
//        }
//        ++__result;
//    }
//    return std::copy(__first2, __last2,
//                     std::copy(__first1, __last1, __result));
//}
2.6 sort 排序
// sort 算法包里的 排序
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main(){
    vector<int> vectorVar;
    vectorVar.push_back(1);
    vectorVar.push_back(2);
    vectorVar.push_back(3);
    vectorVar.push_back(6);
    vectorVar.push_back(5);
    vectorVar.push_back(4);
    vectorVar.push_back(9);
    vectorVar.push_back(5);
    vectorVar.push_back(3);
    vectorVar.push_back(7);
    vectorVar.push_back(8);
    vectorVar.push_back(1);

    sort(vectorVar.begin(),vectorVar.end(), less<int>());

    for (auto it = vectorVar.begin(); it != vectorVar.end(); it ++) {
        cout << *it << endl;
    }


    return 0;
}


// TODO sort 源码

// ...
//sort(_RandomAccessIterator __first,
//    _RandomAccessIterator __last,
//     _Compare __comp) // 仿函数规则
//{
//    //...
//
//
//    std::__sort(__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp));
//}

// TODO 点进 __sort

//...
//__sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
//       _Compare __comp)
//{
// 排序算法
//    if (__first != __last)
//    {
//        std::__introsort_loop(__first, __last,
//                              std::__lg(__last - __first) * 2,
//                              __comp);
//        std::__final_insertion_sort(__first, __last, __comp);
//    }
//}
2.7 random_shuffle 随机打乱元素的顺序
// random_shuffle 算法包里面的 随机打乱元素的顺序

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main(){
    vector<int> vectorVar;
    vectorVar.push_back(65);
    vectorVar.push_back(53);
    vectorVar.push_back(84);
    vectorVar.push_back(11);
    vectorVar.push_back(22);
    vectorVar.push_back(33);
    vectorVar.push_back(44);

    sort(vectorVar.begin(),vectorVar.end(),less<int>());

    random_shuffle(vectorVar.begin(),vectorVar.end());

    for(auto it = vectorVar.begin() ; it != vectorVar.end() ;it++){
        cout << *it << endl;
    }
    return 0;
}

// TODO

// ...
//random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last)
//{
//    // ....
//
//    if (__first != __last)
//        for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
//        {
//            // XXX rand() % N is not uniformly distributed
//            _RandomAccessIterator __j = __first
//                                        + std::rand() % ((__i - __first) + 1);
//            if (__i != __j)
//                std::iter_swap(__i, __j);
//        }
//}
2.8 copy
//TODO copy copy容器1 的元素 到容器2
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main(){
    vector<int> vectorVar;
    vectorVar.push_back(100);
    vectorVar.push_back(200);
    vectorVar.push_back(300);
    vectorVar.push_back(400);
    vectorVar.push_back(500);
    vectorVar.push_back(600);
    vectorVar.push_back(700);

    vector<int> vectorResult;
    vectorResult.resize(vectorVar.size());
    copy(vectorVar.begin(),vectorVar.end(),vectorResult.begin());

    // 打印
    for (auto it = vectorResult.begin(); it != vectorResult.end() ; it++) {
        cout << *it << endl;
    }

    return 0;
}
2.9 replace 替换元素内容
// TODO replace 替换元素内容
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int age;
void set(int age){
    ::age = age;
}

int main(){
    vector<int> vectorVar;
    vectorVar.push_back(100);
    vectorVar.push_back(200);
    vectorVar.push_back(300);
    vectorVar.push_back(400);
    vectorVar.push_back(500);
    vectorVar.push_back(600);

    // 100 - 200 的范围
    replace(vectorVar.begin(),vectorVar.begin() + 2,200,222);
    // 所有范围
    replace(vectorVar.begin(),vectorVar.end(),300,333);

    for(auto itVar = vectorVar.begin() ; itVar != vectorVar.end();itVar++){
        cout << *itVar << endl;
    }
    return 0;
}