c++基础


内存分区模型、引用的基本语法、三种参数传递方式、引用的本质、const修饰参数防止被修改、函数默认值、占位参数、函数重载、面向对象、浅拷贝带来问题、友元、运算符重载、继承、文件读写、模板、STL、函数对象、算法

内存分区模型

c++程序在执行中,将内存分为4个区域

  • 代码区:存放函数体的二进制代码,由操作系统进行管理
  • 全局区:存放全局变量和静态变量以及常量
  • 栈区:由编译器自动分配释放,存放函数的函数值,局部变量等
  • 堆区:由程序员分配和释放,若程序员不释放,程序结束后由操作系统回收

注意事项:

  • 不要返回局部变量的地址
  • 堆区数据利用new关键字进行开辟,使用完需要手动释放,用delete关键字
  • 数组类型数据释放内存,delete[],如果只用delete只会释放数据的第一数据的内存

引用的基本语法

#include <iostream>

using namespace std;

void main() {
	int a = 10;
	int &b = a;
	cout << (int) & a << endl;
	cout << (int) & b << endl;
}

注意:

  • 引用必须初始化
  • 一旦初始化后就不允许进行改变

三种参数传递方式

#include <iostream>

using namespace std;

void swap01(int a,int b) {
	int temp = a;
	a = b;
	b = temp;
}

void swap02(int *a, int *b) {
	int temp = *a;
	*a = *b;
	*b = temp;
}

void swap03(int &a, int &b) {
	int temp = a;
	a = b;
	b = temp;
}

void main() {
	int a;
	int b;

	a = 10;
	b = 20;
	//1.值传递
	//形参不会修饰实参
	swap01(a, b);
	cout << a << endl;
	cout << b << endl;

	a = 10;
	b = 20;
	//2.地址传递
	//形参会修饰实参
	swap02(&a, &b);
	cout << a << endl;
	cout << b << endl;

	a = 10;
	b = 20;
	//3.引用传递
	//形参会修饰实参
	swap03(a, b);
	cout << a << endl;
	cout << b << endl;
}

引用的本质

#include <iostream>

using namespace std;

//发现是引用,转换成 int* const ref = &a;
void func(int& ref) {
	ref = 100; //ref是引用,转换成*ref=100
}
void main() {
	int a = 10;

	//自动转换成int* const ref = &a;指针常量是指针指向不可改,也说明为什么引用不可更改
	int& ref = a;
	ref = 20; //ref是引用,转换成*ref=20

	cout << "a:" << a << endl;
	cout << "ref:" << ref << endl;

	func(a);
}

const修饰参数防止参数被修改

#include <iostream>

using namespace std;

//引用使用的场景,通常用来修饰形参,防止形参被修改
void showValue(const int& v) {
	//v += 10; 不可以修改
	cout << v << endl;
}
void main() {

	//编译器优化 int temp = 10;const int& ref  = temp;
	const int& ref = 10;

	int a = 10;
	showValue(10);

}

函数默认值

#include <iostream>

using namespace std;

//1.如果某个位置参数有默认值,那么从这个位置往后,必须都要有默认值
//2.如果函数声明有默认值,函数实现的时候就不能有默认参数
int func(int a, int b = 10, int c = 1);
int func(int a, int b, int c) {
	return a + b + c;
}

void main() {

	int res = func(1);
	cout << res << endl;

}

占位参数

#include <iostream>

using namespace std;

//占位参数如果没有默认值,调用时必传
int func(int a, int, int =10) {
	return a;
}

void main() {

	int res = func(1,1);
	cout << res << endl;

}

函数重载

  • 同一个作用域下
  • 函数名相同
  • 参数类型不同,或者个数不同,或者顺序不同
  • 函数的返回值不可以作为函数重载的条件
#include <iostream>

using namespace std;

//引用重载案例
int func(int &a) {//int &a = 10;不合法
	return a;
}

int func(const int& a) {
	return a;
}

void main() {

	int res = func(1);//走第二个函数
	cout << res << endl;

}

面向对象

创建类并实例化

#include <iostream>

using namespace std;

class Circle {
	public:
		int r;
		double getRound() {
			return 2 * 3.14 * r;
		}
};

void main() {

	//实例化
	Circle circle;
	circle.r = 10;
	cout << circle.getRound() << endl;

}

构造方法

  • 分为有参、无参、拷贝,必须是public修饰的方法,方法名和类名一致
  • 调用无参构造方法创建对象时,不要用括号方式,因为编译器会把它当作是一个函数的声明
  • 不要利用拷贝构造函数初始化匿名对象,编译器会认为是 Person(p3) 等价于 Person p3; ``` #include #include

using namespace std;

class Person { private: string name; public: Person() { cout « “无参构造函数执行” « endl; } Person(int a) { cout « “有参构造函数执行” « endl; } Person(const Person& p) { cout « “拷贝构造函数执行” « endl; name = p.name; } ~Person() { cout « “析构函数执行” « endl; } };

void main() { //显式法 Person p1; Person p2 = Person(10);//有参构造 Person p3 = Person(p2);//拷贝构造

Person(10);//匿名对象,执行结束后立马被析构掉

//隐式法
Person p4 = 10;//相当于Person p4 = Person(10)
Person p5 = p4;//相当于Person p5 = Person(p4) } ``` ## 构造函数调用规则 默认情况下,c++编译器至少给一个类加3个函数 1.默认构造函数(无参,函数体为空) 2.默认析构函数(无参,函数体为空) 3.默认拷贝构造函数

构造函数调用规则如下:

  • 如果用户定义有参构造函数,c++不再提供默认无参构造,但是会提供默认拷贝构造
  • 如果用户定义拷贝构造函数,c++不再提供其他构造函数

浅拷贝带来的问题

对象中存在堆申请空间的代码,其复制的对象和原对象指向堆中同一个对象,在堆区数据释放时会重复释放导致报错,所以对象中包含在堆区申请空间的代码,应该手动创建拷贝构造函数,将浅拷贝变成深拷贝

类的初始化列表

#include <iostream>

using namespace std;
class Person{
    public:
        int a;
        int b;
        int c;
        Person(int a,int b,int c):a(a),b(b),c(c)
        {
            
        }
};

int main()
{
    Person person(10,20,30);
    std::cout << person.a << endl;
    std::cout << person.b << endl;
    std::cout << person.c << endl;
    return 0;
}

类对象作为成员

#include <iostream>
#include <string>

using namespace std;

class Phone{
    public:
        string name;
        Phone(string name){
            this->name = name;
        }
};
class Person{
    public:
        string name;
        //当其他对象作为本类成员时。先构成其他类对象,再构造本类对象,析构顺序相反
        Phone phone;
        Person(string name,string phone):name(name),phone(phone)
        {
            
        }
};

int main()
{
    Person person("zhang","IPhoneX");
    std::cout << person.name << endl;
    std::cout << person.phone.name << endl;
    return 0;
}

静态成员

#include <iostream>
#include <string>

using namespace std;

class Person{
    public:
        //静态变量所有对象共享,可以通过对象访问也可以通过类直接访问
        static int a;
};

int Person::a = 1;//声明方式初始化静态属性
int main()
{
    Person::a = 10;
    std::cout << Person::a << endl;
    return 0;
}

常函数和常对象

#include <iostream>
#include <string>

using namespace std;

class Person{
    public:
        //this本质是指针常量 Person * const this 指针指向不可以修改
        //const 修饰的成员函数,修饰的是 this 相当于 const Person * const this,this指向的值也不可以修改
        void showPerson() const
        {
            //this->name = "zhanghuan1"; 不可执行
        
            this->a = 10; //该成员属性使用mutable修饰,故可以修改
        }
        void func(){
            
        }
        Person(){
            
        }
        mutable int a;
        string name;
};

int main()
{
    Person p;
    p.showPerson();
    std::cout << p.name << endl;
    std::cout << p.a << endl;
    
    //定义常对象
    const Person p1;
    p1.showPerson();//只能执行常函数
    //p1.func();无法执行
    
    return 0;
}

友元

全局函数作友元

#include <iostream>
#include <string>

using namespace std;


class Building{
    //将全局函数做友元
    friend void goodGay(Building *building);
    public:
        Building(){
            this->meetingRoom = "客厅";
            this->bedRoom = "卧室";
        }
        string meetingRoom;
    private:
        string bedRoom;
};

//全局函数
void goodGay(Building *building){
    cout << "好基友在访问" << building->meetingRoom << endl;
    cout << "好基友在访问" << building->bedRoom << endl;//可访问私有属性
}
int main()
{
    Building building;
    goodGay(&building);
    return 0;
}

类作为友元

#include <iostream>
#include <string>

using namespace std;


class Building{
    //将类做友元
    friend class GoodGay;
    public:
        Building(){
            this->meetingRoom = "客厅";
            this->bedRoom = "卧室";
        }
        string meetingRoom;
    private:
        string bedRoom;
};

class GoodGay{
    public:
        Building *building;
        GoodGay(){
            this->building = new Building;
        }
        void visit(){
            cout << "好基友在访问" << building->meetingRoom << endl;
            cout << "好基友在访问" << building->bedRoom << endl;//可访问私有属性
        }
};

int main()
{
    GoodGay goodGay;
    goodGay.visit();
    return 0;
}

成员函数作友元

#include <iostream>
#include <string>

using namespace std;

class Building;
class GoodGay{
    public:
        Building *building;
        GoodGay();
        void visit();
};

class Building{
    //将成员函数做友元
    friend void GoodGay::visit();
    public:
        Building();
        string meetingRoom;
    private:
        string bedRoom;
};



void GoodGay::visit(){
    cout << "好基友在访问" << building->meetingRoom << endl;
    cout << "好基友在访问" << building->bedRoom << endl;//可访问私有属性
}

GoodGay::GoodGay(){
    this->building = new Building;
}

Building::Building(){
    this->meetingRoom = "客厅";
    this->bedRoom = "卧室";
}





int main()
{
    GoodGay goodGay;
    goodGay.visit();
    return 0;
}

运算符重载

加号运输符重载

#include <iostream>
#include <string>

using namespace std;

class Person{
    public:
        Person(){
            
        }
        Person(int a):a(a){
            
        }
        //成员函数重载加号
        Person operator+(Person p){
            int temp = p.a + this->a;
            Person p1;
            p1.a = temp;
            return p1;
        }
        int a;
};

class Man{
    public:
        Man(){
            
        }
        Man(int a){
            this->a = a;
        }
        int a;
};

//全局函数重载加号
Man operator+(Man &man1,Man &man2){
    int temp = man1.a + man2.a;
    Man man(temp);
    return man;
}

//运算符重载也可以函数重载
Man operator+(Man &man1,int num){
    int temp = man1.a + num;
    Man man(temp);
    return man;
}

int main()
{
    Person p1(10);
    Person p2(20);
    Person p3 = p1 + p2;
    cout << p3.a << endl;
    
    Man man1(10);
    Man man2(20);
    Man man3 = man1 + man2;
    cout << man3.a << endl;
    
    Man man4 = man3 + 20;
    cout << man4.a << endl;
    
    return 0;
}

左移运算符重载

#include <iostream>
#include <string>

using namespace std;

class Person{
    friend ostream& operator<<(ostream &cout,Person &p);
    public:
        Person(){
            
        }
        Person(int a,int b){
            this->a = a;
            this->b = b;
        }
    private:
        int a;
        int b;
};

//重载左移运算符
ostream& operator<<(ostream &cout,Person &p){
    cout << "a=" << p.a << ",b=" << p.b;
    return cout;
}

int main()
{
    Person p(10,20);
    cout << p << endl;
    
    return 0;
}

递增运算符重载

#include <iostream>
#include <string>

using namespace std;

class MyInteger{
    friend ostream& operator<<(ostream& cout,MyInteger myInteger);
    public:
        MyInteger(){
            this->num = 0;
        }
        MyInteger(int num){
            this->num = num;
        }
        //定义前置递增
        MyInteger& operator++(){
            this->num++;
            return *this; 
        }
        //定义后置递增
        MyInteger operator++(int){
            //拷贝构造函数创建一个新对象
            MyInteger temp = *this;
            this->num++;
            return temp; 
        }
    private:
        int num;
};

ostream& operator<<(ostream& cout,MyInteger myInteger){
    cout << myInteger.num;
    return cout;
}


int main()
{
    MyInteger myInteger(10);
    cout << myInteger << endl;
    
    cout << ++myInteger << endl; //11
    cout << myInteger++ << endl; //11
    return 0;
}

赋值运算符重载

#include <iostream>
#include <string>

using namespace std;

class MyInteger{
    friend ostream& operator<<(ostream& cout,MyInteger& myInteger);
    public:
        MyInteger(){
            this->num = new int(0);
        }
        MyInteger(int num){
            this->num = new int(num);
        }
        ~MyInteger(){
            if(this->num != NULL){
                delete this->num;
                this->num = NULL;
            }
        }
       MyInteger& operator=(MyInteger& myInteger){
           //清空
           if(this->num != NULL){
               delete this->num;
               this->num = NULL;
           }
           //深拷贝
           this->num = new int(*myInteger.num);
           return *this;
       }
    private:
        int *num;
};

ostream& operator<<(ostream& cout,MyInteger& myInteger){//myInteger如果不传指向析构函数会执行两次,除非重写拷贝构造函数
    cout << *myInteger.num;
    return cout;
}


int main()
{
    MyInteger myInteger1(10);
    MyInteger myInteger2(20);
    MyInteger myInteger3(30);
    myInteger3 = myInteger2 = myInteger1;
    
    cout << myInteger1 << endl;
    cout << myInteger2 << endl;
    cout << myInteger3 << endl;
    return 0;
}

关系运算符重载

#include <iostream>
#include <string>

using namespace std;

class Person{
    public:
        Person(string name){
            this->name = name;
        }
        bool operator==(Person& person){
            if(person.name == this->name){
                return true;
            }
            return false;
        }
        bool operator!=(Person& person){
            if(person.name != this->name){
                return true;
            }
            return false;
        }
        string name;
};

int main()
{
    Person p1("zhang");
    Person p2("zhang1");
    std::cout << (p1 == p2) << endl; //0
    std::cout << (p1 != p2) << endl; //1
    return 0;
}

函数调用运算符重载

#include <iostream>
#include <string>

using namespace std;

class Myadd{
    public:
        int operator()(int a,int b){
            return a + b;
        }
};

int main()
{
    Myadd myadd1;
    int res1 = myadd1(10,10);
    cout << res1 << endl;
    
    //匿名对象调用
    cout << Myadd()(10,20) << endl;
    return 0;
}

继承

三种继承方式

#include <iostream>
#include <string>

using namespace std;

class Base{
    public:
        Base(){
            a = 10;
            b = 20;
            c = 30;
        }
        int a;
    protected:
        int b;
    private:
        int c;
};

//3中继承方式

class Son1:public Base{
    //继承过来的所有公共属性仍然为公共属性
};

class Son2:protected Base{
    //继承过来的所有公共属性变成保护属性
};

class Son3:private Base{
    //继承过来的所有公共属性、保护属性都变成私有属性
};


int main()
{
    Son1 son1;
    cout << son1.a << endl;
    
    return 0;
}

同名属性访问

#include <iostream>
#include <string>

using namespace std;

class Base{
    public:
        Base(){
            a = 10;
            b = 20;
            c = 30;
        }
        int a;
    protected:
        int b;
    private:
        int c;
};


class Son:public Base{
    public:
        Son(){
            a = 110;
        }
        int a;
};


int main()
{
    Son son;
    //默认访问子类的属性a
    cout << son.a << endl;
    //范围父类的属性a
    cout << son.Base::a << endl;
    
    return 0;
}

多继承语法

#include <iostream>
#include <string>

using namespace std;

class Base1{
    public:
        Base1(){
            a = 10;
        }
        int a;
};

class Base2{
    public:
        Base2(){
            a = 20;
        }
        int a;
};

//多继承语法
class Son:public Base1,public Base2{
    public:
        Son(){
            a = 110;
        }
        int a;
};


int main()
{
    Son son;
    
    cout << son.a << endl;
    cout << son.Base1::a << endl;
    cout << son.Base2::a << endl;
    
    return 0;
}

菱形继承

#include <iostream>
#include <string>

using namespace std;

class Animal{
    public:
     int a;
};

//通过虚继承解决子类继承的a属性的指向不明问题
class Sheep:virtual public Animal{
    
};

class Tuo:virtual public Animal{
    
};

class SheepTuo:public Sheep,public Tuo{
    
};


int main()
{
    SheepTuo sheepTuo;
    sheepTuo.a = 1;
    cout << sheepTuo.Sheep::a << endl; //1
    cout << sheepTuo.Tuo::a << endl; //1
    cout << sheepTuo.a << endl; //1
    
    return 0;
}

多态

多态分两类

  • 静态多态:函数重载和运算符重载属于静态多态,复用函数名
  • 动态多态:派生类和虚函数实现运行时多态

静态多态和动态多态区别

  • 静态多态的函数地址早绑定,编译阶段确定函数地址
  • 动态多态的函数地址晚绑定,运行阶段确定函数地址
#include <iostream>
#include <string>

using namespace std;

class Animal{
    public:
     //使用虚函数
     virtual void speak(){
         cout << "动物在说话" << endl;
     }
};

class Cat:public Animal{
    public:
     void speak(){
         cout << "猫在说话" << endl;
     }
};

class Dog:public Animal{
    public:
     void speak(){
         cout << "狗在说话" << endl;
     }
};

void doSpeak(Animal &animal){
    animal.speak();
}

int main()
{
    Cat cat;
    doSpeak(cat); //猫在说话
    
    Dog dog;
    doSpeak(dog); //狗在说话
    
    return 0;
}

虚函数原理

类中有虚函数,内的内部会有一个虚函数表记录虚函数的地址,当子类重写父类的虚函数时,子类的虚函数表内部会替换成子类函数的地址,从而实现多态

纯虚函数

语法 virtual 返回值类型 虚函数名 (参数列表) = 0

但类中有了纯虚函数,这个类就是抽象类

抽象类特点

  • 无法实例化对象
  • 子类必须重写抽象类中的虚函数,否则也属于抽象类

虚析构和纯虚析构

多态使用时,如果子类中有属性开辟到堆区,那么弗雷指针子啊释放时无法调用到子类的析构代码,导致内存泄漏 解决方式:将父类中的析构函数改为虚析构或者纯虚析构

案例

#include <iostream>
#include <string>

using namespace std;

class Cpu{
    public:
        virtual void calculate() = 0;
        virtual ~Cpu(){};
};

class DisplayCard{
    public:
        virtual void display() = 0;
        virtual ~DisplayCard(){};
};

class Storage{
    public:
        virtual void store() = 0;
        virtual ~Storage(){};
};

class IntelCpu:public Cpu{
    public:
        virtual void calculate(){
            cout << "IntelCpu 开始计算" << endl;
        }
        ~IntelCpu(){
            cout << "IntelCpu 析构函数执行" <<endl;
        }
};

class NvdCard:public DisplayCard{
    public:
        virtual void display(){
            cout << "NvdCard 开始工作" << endl;
        }
        ~NvdCard(){
            cout << "NvdCard 析构函数执行" <<endl;
        };
};

class SamSungDisk:public Storage{
    public:
        virtual void store(){
            cout << "三星硬盘 开始工作" << endl;
        }
        ~SamSungDisk(){
            cout << "三星硬盘 析构函数执行" <<endl;
        };
};

class Computer{
    public:
        Computer(Cpu *cpu,DisplayCard *displayCard,Storage *storage){
            this->cpu = cpu;
            this->displayCard = displayCard;
            this->storage = storage;
        }
        void doWork(){
            cpu->calculate();
            displayCard->display();
            storage->store();
        }
        ~Computer(){
            cout << "Computer 析构函数执行" << endl;
            if(cpu != NULL){
                delete cpu;
                cpu = NULL;
            }
            if(displayCard != NULL){
                delete displayCard;
                displayCard = NULL;
            }
            if(storage != NULL){
                delete storage;
                storage = NULL;
            }
        }
    private:
        Cpu *cpu;
        DisplayCard *displayCard;
        Storage *storage;
};

int main()
{
    Computer *computer = new Computer(new IntelCpu(),new NvdCard(),new SamSungDisk());
    computer->doWork();
    
    delete computer;
    /**
     *  IntelCpu 开始计算
        NvdCard 开始工作
        三星硬盘 开始工作
        Computer 析构函数执行
        IntelCpu 析构函数执行
        NvdCard 析构函数执行
        三星硬盘 析构函数执行
     * /
    return 0;
}

文件读写

普通方式文件读写

#include <iostream>
#include <string>
#include <fstream>

using namespace std;


void test1() {
    //写入
    ofstream ofs;
    ofs.open("test.txt", ios::out);

    ofs << "姓名:张三" << endl;
    ofs << "性别:男" << endl;
    ofs << "年龄:23" << endl;

    ofs.close();  
}

void test2() {
    //读取
    ifstream ifs;
    ifs.open("test.txt", ios::in);
    if (!ifs.is_open()) {
        cout << "文件打开失败" << endl;
        return;
    }

    char buf[1024] = { 0 };

    //方式一
    /**
    while (ifs >> buf) {
        cout << buf << endl;
    }
    **/

    //方式二
    /**
    while (ifs.getline(buf, sizeof(buf))) {
        cout << buf << endl;
    }
    **/

    //方式三
    /**
    string bf;
    while (getline(ifs, bf)) {
        cout << bf << endl;
    }
    **/

    //方式四
    char c;
    while ( (c = ifs.get()) != EOF) {
        cout << c;
    }
    ifs.close();
}


void main() {
    test2();
}

二进制方式读写

#include <iostream>
#include <string>
#include <fstream>

using namespace std;

class Person {
public:
    string name;
    int age;
};

void test1() {
    //写入
    ofstream ofs;
    ofs.open("person.txt", ios::out | ios::binary);

    Person p = { "zhanghuan",22 };

    ofs.write((const char*)&p, sizeof(p));

    ofs.close();  
}

void test2() {
    //读取
    ifstream ifs;
    ifs.open("person.txt", ios::in | ios::binary);
    if (!ifs.is_open()) {
        cout << "文件打开失败" << endl;
        return;
    }
    Person p;

    ifs.read((char*)&p, sizeof(Person));

    cout << p.name << endl;

    cout << p.age << endl;
    
    ifs.close();
}


int main() {
    //test1();
    test2();
    return 0;
}

模板

基本使用

#include <cstdio>

template<typename T>
void swap(T &a, T &b)
{ 
    T t = a;
    a = b;
    b = t;
}

int main()
{
    int x = 3, y = 6;
    printf("%d %d\n", x, y);
    swap<int>(x, y);//制定类型,可不传int则会自动推导
    printf("%d %d\n", x, y);
    return 0;
}

注意事项

  • 自动类型推导,必须推导出一致数据类型T才可以使用
  • 模板必须要确定出T的数据类型,才可以使用

选择排序案例

#include <cstdio>

template<typename T>
void swap(T &a, T &b)
{ 
    T t = a;
    a = b;
    b = t;
}

template<typename T>
void printArray(T arr[],int len){
    printf("[");
    for (int i = 0; i < len; ++i) {
        printf("%d", arr[i]);
        if (i < len - 1) {
            printf(", ");
        }
    }
    printf("]\n");
}

template<typename T>
void mySort(T arr[],int len){
    for(int i=0;i<len;i++){
        int maxIndex = i;
        for (int j = i+1; j < len; j++) {
            if(arr[maxIndex] < arr[j]){
                maxIndex = j;
            }
        }
        if(i != maxIndex){
            swap(arr[i],arr[maxIndex]);
        }
    }
}

int main()
{
    int arr[] = {1,2,4,6,3};
    int len = sizeof(arr)/sizeof(int);
    printArray(arr,len);
    mySort(arr,len);
    printArray(arr,len);//64321
}

类模板成员函数创建时机

在运行时创建

类模板与继承

#include <iostream>
using namespace std;

template<class T>
class Base{
	T obj1;
};

class Son1:public Base<int>{//必须要知道父类中T的类型才可以继承
};

template<class T1,class T2>
class Son2:public Base<T1>{
	T2 obj2;
};
	
int main()
{
   cout << "Hello World1";
   return 0;
}

类模板成员函数类外实现

#include <iostream>
#include <string>
using namespace std;

template<class T1,class T2>
class Person{
	public:
		T1 name;
		T2 age;
		Person(T1 name,T2 age);
		void showPerson();
};

template<class T1,class T2>
Person<T1,T2>::Person(T1 name,T2 age){
	this->name = name;
	this->age = age;
}

template<class T1,class T2>
void Person<T1,T2>::showPerson(){
	cout << "姓名:" << name << ",年龄:" << age << endl;
}

	
int main()
{
	
	Person<string,int> p("zh",22);
	p.showPerson();
	return 0;
}

类模板分文件编写

  • 直接包含源文件
  • 将.h和.cpp的内容写到一起,将后缀名改为.hpp

类模板与友元

#include <iostream>
#include <string>

using namespace std;

template<class T1,class T2>
class Person;

template<class T1,class T2>
void printPerson2(Person<T1,T2> p){
    cout << "name:" << p.name << " age:" << p.age << endl;
}

template<class T1,class T2>
class Person{
    //在类中定义全局函数
    friend void printPerson1(Person p){
        cout << "name:" << p.name << " age:" << p.age << endl;
    }
    
    //类外实现全局函数
    friend void printPerson2<>(Person<T1,T2> p);
    public:
        Person(T1 name,T2 age){
            this->name = name;
            this->age = age;
        }
    private:
        T1 name;
        T2 age;
};


int main()
{
    Person<string,int> p("zhang",22);
    
    printPerson1(p);
    printPerson2(p);
    return 0;
}

自定义数组

#pragma
#include <iostream>

using namespace std;

template<class T>
class MyArray {
public:
    T* array;
    int len;
    int capacity;
    MyArray(int capacity) {
        this->capacity = capacity;
        this->array = new T[this->capacity];
        this->len = 0;
    }
    MyArray(const MyArray& myArray) {
        this->capacity = myArray.capacity;
        this->array = new T[myArray.capacity];
        this->len = myArray.len;
        for (int i = 0; i < len; ++i) {
            this->array[i] = myArray.array[i];
        }
    }
    ~MyArray() {
        delete[] array;
    }
    MyArray& operator =(const MyArray& myArray) {
        if (this->array != NULL){
            delete[] this->array;
            this->array = NULL;
        }
        this->len = myArray.len;
        this->array = new T[len];
        this->capacity = myArray.capacity;
        for (int i = 0; i < len; ++i) {
            this->array[i] = myArray.array[i];
        }
        return *this;
    }
    T& operator [](int i) {
        return this->array[i];
    }
    void push(const T& t) {
        if (len == capacity) {
            return;
        }
        this->array[len] = t;
        this-> len ++;
    }
    void pop() {
        if (len == 0) {
            return;
        }
        this->len --;
    }
    int getLength() {
        return this->len;
    }
    int getCapacity() {
        return this->capacity;
    }
};

STL

在 C++ 中,STL(Standard Template Library)是一个非常重要的组成部分,它提供了大量的通用模板类和函数,用于处理常见的数据结构和算法。STL 是 C++ 标准库的一部分,并且被广泛用于各种 C++ 程序中。

STL 主要由以下几个组件组成:

容器(Containers):STL 提供了多种类型的容器,如向量(std::vector)、列表(std::list)、双端队列(std::deque)、集合(std::set)、映射(std::map)等。这些容器类模板用于存储和管理数据元素。 迭代器(Iterators):迭代器提供了一种访问容器中元素的方式,它们类似于指针,但更为通用。迭代器可以遍历容器中的所有元素,并允许我们读取或修改这些元素的值。 算法(Algorithms):STL 提供了大量用于操作容器中元素的算法,如排序(std::sort)、查找(std::find)、复制(std::copy)等。这些算法通常与容器和迭代器一起使用,以实现对容器中数据的复杂操作。 函数对象(Function Objects):函数对象(也称为仿函数或函数子)是 STL 中一个重要的概念。它们是可以像函数一样被调用的对象,通常用于作为算法的参数,以定义算法的行为。 适配器(Adapters):适配器用于修改容器或迭代器的行为,以适应不同的算法需求。例如,std::stack 和 std::queue 是基于其他容器(如 std::deque)的适配器,它们提供了栈和队列的接口。 分配器(Allocators):分配器用于管理容器中元素的内存分配和释放。虽然大多数程序员不需要直接使用分配器,但它们为 STL 提供了高度的灵活性和可定制性。 通过使用 STL,程序员可以更加高效地编写 C++ 代码,因为 STL 中的组件已经经过了优化和测试,并且与 C++ 标准库的其他部分紧密集成。此外,STL 的模板特性使得代码更加通用和可重用,减少了编写重复代码的需要。

vector

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

using namespace std;

int main() {
    vector<int> v;
    v.push_back(11);
    v.push_back(15);
    v.push_back(7);

    for (size_t i = 0; i < v.size(); ++i) {
        cout << v[i] << " ";
    }
    cout << endl; // 输出: 11 15 7

    // 使用迭代器遍历vector
    for (vector<int>::iterator it = v.begin(); it != v.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl; // 输出: 11 15 7

    //排序
    sort(v.begin(), v.end(), [](int a, int b) { return a > b; });

    for (size_t i = 0; i < v.size(); ++i) {
        cout << v[i] << " ";
    }
    cout << endl; // 输出: 7 11 15
    return 0;
}

使用swap压缩空间

#include <iostream>
#include <vector>

using namespace std;

int main()
{

    vector<int> v;
    for (int i = 0; i < 17; ++i) {
        v.push_back(i);
    }
    v.pop_back();
    v.pop_back();
    v.pop_back();
    v.pop_back();
    v.pop_back();

    cout << "capacity: " << v.capacity() << endl; //32
    
    //创建匿名对象,将匿名对象和原来的对象交换,达到压缩空间的目的
    vector<int> (v).swap(v);

    cout << "capacity: " << v.capacity() << endl; //12

    return 0;
}

预分配空间

#include <iostream>
#include <vector>

using namespace std;

int main()
{

    vector<int> v;
    int num = 0;
    int* ptr = NULL;
    for (int i = 0; i < 17; ++i) {
        v.push_back(i);
        if (ptr != &v[0]){
            ptr = &v[0];
            num++;
        }
    }

    //查看扩容次数 6-1=5
    cout << "num: " << num << endl;

    vector<int> v1;
    v1.reserve(20);//预先申请20容量,避免多次扩容消耗性能
    int num1 = 0;
    int* ptr1 = NULL;
    for (int i = 0; i < 17; ++i) {
        v1.push_back(i);
        if (ptr1 != &v1[0]){
            ptr1 = &v1[0];
            num1++;
        }
    }

    //查看扩容次数 1-1=0
    cout << "num1: " << num1 << endl;

    return 0;
}

deque

基础

#include <iostream>
#include <deque>
#include <algorithm>

using namespace std;

//打印
void printDq(const deque<int>& d){
    for (deque<int>::const_iterator it = d.begin();it != d.end();it++ ) {
        cout << *it << " ";
    }
    cout << endl;
}

int main() {

    deque<int> dq;
    for (int i = 0; i < 5; ++i) {
        dq.push_back(i);
    }

    printDq(dq);

    //赋值
    deque<int> d1 = dq;
    printDq(d1);

    //传入开始结束
    deque<int> d2(dq.begin(),dq.end());
    printDq(d2);

    //10个100
    deque<int> d3(10,100);
    printDq(d3);

    //构造函数赋值
    deque<int> d4(d3);
    printDq(d4);

    //assign方式赋值
    deque<int> d5;
    d5.assign(d4.begin(),d4.end());
    printDq(d5);

    //10个10
    deque<int> d6;
    d6.assign(10,10);
    printDq(d6);


    cout << "长度:" << d6.size() << endl;

    //重新设置长度
    d6.resize(5);
    printDq(d6);
    //默认补0
    d6.resize(10);
    printDq(d6);
    //指定补5
    d6.resize(15,5);
    printDq(d6);

    //插入
    d6.push_back(100);
    d6.push_front(1);
    printDq(d6);//1 10 10 10 10 10 0 0 0 0 0 5 5 5 5 5 100
    //区间插入
    d2.insert(d2.begin(),d1.begin(),d1.end());
    printDq(d2);//0 1 2 3 4 0 1 2 3 4

    //头删除
    d3.pop_front();
    printDq(d3);
    //尾删除
    d3.pop_back();
    printDq(d3);

    //指定删除
    deque<int>::iterator it = d2.begin();
    it ++;
    d2.erase(it);
    printDq(d2);//0 2 3 4 0 1 2 3 4

    //清空,相当于clear
    d2.erase(d2.begin(),d2.end());
    printDq(d2);

    //排序,默认从小到大
    sort(d6.begin(),d6.end());
    printDq(d6);

    return 0;
}

案例

  • 创建5名选手,放到vector中
  • 遍历vector容器,取出每一个选手,进行10个打分放到deque中
  • sort算法堆deque容器中分数排序,去掉最高分和最低分
  • 计算每个选手deque中的平均分
#include <iostream>
#include <vector>
#include <deque>
#include <algorithm>
#include <string>
#include <ctime>

using namespace std;

class Person{
public:
    Person(string name){
        this->name = name;
    }
    void setAvgScore(int score){
        this->avgScore = score;
    }
    string getName(){
        return this->name;
    }
    int getAvgScore(){
        return this->avgScore;
    }
private:
    string name;
    int avgScore;
};

int main() {

    //随机种子
    srand((unsigned int) time(NULL));

    //创建5名选手
    string names = "ABCDE";
    vector<Person> persons;
    for (int i = 0; i < 5; ++i) {
        string  name = "选手";
        name += names[i];
        Person p(name);
        persons.push_back(p);
    }

    //给每个选手打分
    for (int i=0;i<persons.size();i++) {
        Person& person = persons[i];

        deque<int> scores;
        for (int j = 0; j < 10; ++j) {
            int score = rand()%41 + 60;
            scores.push_back(score);
        }
        //排序
        sort(scores.begin(),scores.end());
        //去掉最高分和最低分
        scores.pop_back();
        scores.pop_front();
        //计算平均分
        int sum = 0;
        for (int j = 0; j < scores.size(); ++j) {
            sum += scores[j];
        }
        int avg = sum/scores.size();
        person.setAvgScore(avg);
    }

    //打印5名选手的分数
    for (int i = 0; i < persons.size(); ++i) {
        Person person = persons[i];
        cout << "姓名:" <<person.getName() << " 得分:" << person.getAvgScore() << endl;
    }
    return 0;
}

#include <iostream>
#include <stack>

using namespace std;

int main() {

    stack<int> s;

    s.push(1);
    s.push(2);
    s.push(3);
    s.push(4);
    s.push(5);

    while (!s.empty()){
        cout << "栈顶: " << s.top() << endl;
        cout << "栈大小: " << s.size() << endl;
        //出栈
        s.pop();
    }

    return 0;
}

队列

#include <iostream>
#include <queue>
#include <string>
using namespace std;

class Person{
public:
    Person(string name,int age){
        this->name = name;
        this->age = age;
    }
    string name;
    int age;
    void print(){
        cout << "姓名: " << name << " 年龄: " << age << endl;
    }
};

int main() {

    queue<Person> q;

    Person p1("唐僧",30);
    Person p2("孙悟空",1000);
    Person p3("猪八戒",900);
    Person p4("沙僧",800);

    q.push(p1);
    q.push(p2);
    q.push(p3);
    q.push(p4);

    while (!q.empty()){
        q.front().print();
        q.pop();
    }

    return 0;
}

list

构造函数

#include <iostream>
#include <list>
using namespace std;

void printList(list<int>& ls){
    for (list<int>::iterator it = ls.begin();it != ls.end();it++) {
        cout << *it << " ";
    }
    cout << endl;
}

int main() {

    list<int> l1;
    l1.push_back(1);
    l1.push_back(2);
    l1.push_back(3);
    l1.push_back(4);

    printList( l1);

    list<int> l2(l1.begin(),l1.end());
    printList(l2);

    list<int> l3(l2);
    printList(l3);

    list<int> l4(10,100);
    printList(l4);

    return 0;
}

赋值和交换

#include <iostream>
#include <list>
#include <algorithm>
#include <string>
using namespace std;

void printList(list<int>& ls){
    for (list<int>::iterator it = ls.begin();it != ls.end();it++) {
        cout << *it << " ";
    }
    cout << endl;
}

int main() {

    list<int> l1;
    l1.push_back(1);
    l1.push_back(2);
    l1.push_back(3);
    l1.push_back(4);

    printList( l1);

    //=赋值
    list<int> l2 = l1;
    printList(l2);

    //assign 赋值
    list<int> l3;
    l3.assign(l1.begin(),l1.end());
    printList(l3);

    list<int> l4;
    l4.assign(10,100);
    printList(l4);

    //交换
    cout << "交换前" << endl;
    printList(l1);
    printList(l4);

    l4.swap(l1);

    cout << "交换后" << endl;
    printList(l1);
    printList(l4);

    return 0;
}

指定大小

#include <iostream>
#include <list>

using namespace std;

void printList(list<int>& ls){
    for (list<int>::iterator it = ls.begin();it != ls.end();it++) {
        cout << *it << " ";
    }
    cout << endl;
}

int main() {

    list<int> l1;
    l1.push_back(1);
    l1.push_back(2);
    l1.push_back(3);
    l1.push_back(4);

    if (l1.empty()){
        cout << "为空" << endl;
    }else{
        cout << "不为空" << endl;
        cout << "长度为:" << l1.size() << endl;
    }

    //重新指定大小
    l1.resize(10);
    printList(l1);

    //缩小时,多余元素会被删除
    l1.resize(2);
    printList(l1);

    return 0;
}

插入和删除

#include <iostream>
#include <list>

using namespace std;

void printList(list<int>& ls){
    for (list<int>::iterator it = ls.begin();it != ls.end();it++) {
        cout << *it << " ";
    }
    cout << endl;
}

int main() {

    list<int> l1;
    l1.push_back(1);
    l1.push_back(2);
    l1.push_back(3);
    l1.push_back(4);

    //头插入
    l1.push_front(10);
    l1.push_front(20);
    printList(l1);//20 10 1 2 3 4

    //insert插入
    list<int>::iterator it = l1.begin();
    l1.insert(++it,1000);
    printList(l1);//20 1000 10 1 2 3 4

    //删除
    it = l1.begin();
    l1.erase(it);
    printList(l1);//1000 10 1 2 3 4

    //移除 删除所有满足条件的数据
    l1.push_back(10000);
    l1.push_back(10000);
    l1.push_back(10000);
    l1.push_back(10000);
    l1.push_back(10000);
    l1.remove(10000);
    printList(l1); //1000 10 1 2 3 4

    //清空
    l1.clear();
    printList(l1);

    return 0;
}

数据存取

#include <iostream>
#include <list>
#include <algorithm>
#include <string>
using namespace std;

void printList(list<int>& ls){
    for (list<int>::iterator it = ls.begin();it != ls.end();it++) {
        cout << *it << " ";
    }
    cout << endl;
}

int main() {

    list<int> l1;
    l1.push_back(1);
    l1.push_back(2);
    l1.push_back(3);
    l1.push_back(4);

    //list是链表,不支持随机范围,[]和at都不可用

    cout << "第一个元素:" << l1.front() << endl;
    cout << "最后一个元素:" << l1.back() << endl;
    
    list<int>::iterator it = l1.begin();
    it++;
    it--;
    //不支持it+1

    return 0;
}

排序和反转

#include <iostream>
#include <list>
#include <string>
using namespace std;

void printList(list<int>& ls){
    for (list<int>::iterator it = ls.begin();it != ls.end();it++) {
        cout << *it << " ";
    }
    cout << endl;
}

bool compare(int v1,int v2){
    return v1 > v2;
}

int main() {

    list<int> l1;
    l1.push_back(5);
    l1.push_back(2);
    l1.push_back(3);
    l1.push_back(4);

    cout << "排序前" << endl;
    printList(l1);
    l1.sort();
    cout << "排序后" << endl;
    printList(l1);

    //从大到校排序,需要自定义排序函数
    l1.sort(compare);
    cout << "从大到小排序后:" << endl;
    printList(l1);

    //反转
    l1.reverse();
    printList(l1);

    return 0;
}

排序案例

  • 将Person进行排序,对象属性为姓名、年龄、身高
  • 排序规则,按照年龄升序,如果年龄相同安装身高降序
#include <iostream>
#include <list>
#include <string>
using namespace std;

class Person{
public:
    Person(string name,int age,int height){
        this->name = name;
        this->age = age;
        this->height = height;
    }
    string name;
    int age;
    int height;
};

void printList(list<Person>& ls){
    for (list<Person>::iterator it = ls.begin();it != ls.end();it++) {
        cout << " 姓名:" << it->name << " 年龄:" << it->age << " 身高:" << it->height << endl;
    }
}

bool compare(Person& p1,Person& p2){
    if (p1.age == p2.age){
        return p1.height > p2.height;
    } else{
        return p1.age < p2.age;
    }
}

int main() {

    list<Person> ls;

    Person p1("刘备",35,175);
    Person p2("曹操",45,180);
    Person p3("孙权",40,170);
    Person p4("赵云",25,190);
    Person p5("张飞",35,160);
    Person p6("关羽",35,200);

    ls.push_back(p1);
    ls.push_back(p2);
    ls.push_back(p3);
    ls.push_back(p4);
    ls.push_back(p5);
    ls.push_back(p6);

    cout << "排序前:" << endl;
    printList(ls);

    ls.sort(compare);

    cout << "排序后:" << endl;
    printList(ls);

    return 0;
}

set

构造和赋值

#include <iostream>
#include <set>
#include <string>
using namespace std;


void printSet(set<int>& s){
    for (set<int>::iterator it = s.begin();it != s.end();it++) {
        cout << *it << " ";
    }
    cout << endl;
}

int main() {

    set<int> s;

    s.insert(10);
    s.insert(40);
    s.insert(30);
    s.insert(20);
    s.insert(30);

    printSet(s);//10 20 30 40

    //拷贝构造
    set<int> s2(s);

    return 0;
}

容器大小和交换

#include <iostream>
#include <set>
#include <string>
using namespace std;


void printSet(set<int>& s){
    for (set<int>::iterator it = s.begin();it != s.end();it++) {
        cout << *it << " ";
    }
    cout << endl;
}

int main() {

    set<int> s;

    s.insert(10);
    s.insert(40);
    s.insert(30);
    s.insert(20);
    s.insert(30);

    if (s.empty()){
        cout << "容器是空的" << endl;
    }else{
        cout << "大小:" << s.size() << endl;
    }

    set<int> s1;

    s1.insert(100);
    s1.insert(400);

    cout << "交换前" << endl;
    printSet(s);
    printSet(s1);
    s.swap(s1);
    cout << "交换后" << endl;
    printSet(s);
    printSet(s1);

    return 0;
}

插入和删除

#include <iostream>
#include <set>
#include <string>
using namespace std;


void printSet(set<int>& s){
    for (set<int>::iterator it = s.begin();it != s.end();it++) {
        cout << *it << " ";
    }
    cout << endl;
}

int main() {

    set<int> s;

    s.insert(10);
    s.insert(40);
    s.insert(30);
    s.insert(20);
    s.insert(30);

    //删除
    s.erase(s.begin());
    printSet(s);//20 30 40

    s.erase(30);
    printSet(s);//20 30 40

    s.erase(s.begin(),s.end());
    s.clear();

    return 0;
}

查找和统计

#include <iostream>
#include <set>
#include <string>
using namespace std;


void printSet(set<int>& s){
    for (set<int>::iterator it = s.begin();it != s.end();it++) {
        cout << *it << " ";
    }
    cout << endl;
}

int main() {

    set<int> s;

    s.insert(10);
    s.insert(40);
    s.insert(30);
    s.insert(20);
    s.insert(30);

    //查找
    set<int>::iterator it = s.find(30);
    if (it != s.end()){
        cout << "找到了" << endl;
    }else{
        cout << "没找到" << endl;
    }

    //统计
    int num = s.count(30);
    cout << num << endl;//1

    multiset<int> ms;
    ms.insert(1);
    ms.insert(1);
    ms.insert(1);
    ms.insert(1);

    int num1 = ms.count(1);
    cout << num1 << endl;//4

    return 0;
}

pair

#include <iostream>
#include <string>
using namespace std;



int main() {
    //第一种方式
    pair<string,int> p("zh",12);
    cout << "姓名: " << p.first << " 年龄: " << p.second << endl;

    //第二种方式
    pair<string,int> p2 = make_pair("zh",13);
    cout << "姓名: " << p2.first << " 年龄: " << p2.second << endl;

    return 0;
}

指定排序规则

#include <iostream>
#include <set>
#include <string>
using namespace std;


class MyCompare{
public:
    bool operator()(int v1,int v2) const{
        return v1 > v2;
    }
};

int main() {
    set<int,MyCompare> s;

    s.insert(10);
    s.insert(40);
    s.insert(30);
    s.insert(20);
    s.insert(30);

    for (set<int,MyCompare>::iterator it = s.begin();it != s.end();it++) {
        cout << *it << " ";
    }
    cout << endl;

    return 0;
}

map

构造和赋值

#include <iostream>
#include <map>
#include <string>
using namespace std;


void printMap(map<int,int> &m){
    for (map<int,int>::iterator it = m.begin();it != m.end();it++){
        cout << "key=" << it->first << " value=" << it->second << endl;
    }
}

int main() {
    map<int,int> m;

    m.insert(pair<int,int>(1,1));
    m.insert(pair<int,int>(2,1));

    printMap(m);

    //拷贝构造
    map<int,int> m2(m);
    printMap(m2);

    //赋值
    map<int,int> m3;
    m3 = m2;
    printMap(m3);

    return 0;
}

容器大小和交换

#include <iostream>
#include <map>
#include <string>
using namespace std;


void printMap(map<int,int> &m){
    for (map<int,int>::iterator it = m.begin();it != m.end();it++){
        cout << "key=" << it->first << " value=" << it->second << endl;
    }
}

int main() {
    map<int,int> m;
    m.insert(pair<int,int>(1,1));

    if (m.empty()){
        cout << "空的map" << endl;
    }else{
        cout << m.size() << endl;
    }

    map<int,int> m1;
    m1.insert(pair<int,int>(2,1));

    cout << "交换前:" << endl;
    printMap(m);
    printMap(m1);

    m.swap(m1);
    cout << "交换后:" << endl;
    printMap(m);
    printMap(m1);

    return 0;
}

插入和删除

#include <iostream>
#include <map>
#include <string>
using namespace std;


void printMap(map<int,int> &m){
    for (map<int,int>::iterator it = m.begin();it != m.end();it++){
        cout << "key=" << it->first << " value=" << it->second << endl;
    }
}

int main() {
    map<int,int> m;

    //插入
    m.insert(pair<int,int>(1,1));
    m.insert(make_pair(2,1));
    m.insert(map<int,int>::value_type (3,1));
    m[4] = 4;

    printMap(m);

    //删除
    m.erase(m.begin());
    printMap(m);

    m.erase(3);
    printMap(m);

    m.clear();
    printMap(m);
    
    return 0;
}

查找和统计

#include <iostream>
#include <map>
#include <string>
using namespace std;


void printMap(map<int,int> &m){
    for (map<int,int>::iterator it = m.begin();it != m.end();it++){
        cout << "key=" << it->first << " value=" << it->second << endl;
    }
}

int main() {
    map<int,int> m;

    m.insert(pair<int,int>(1,1));
    m.insert(pair<int,int>(2,1));
    m.insert(pair<int,int>(3,1));

    //查找
    map<int,int>::iterator pos = m.find(3);
    if (pos != m.end()){
        cout << "key=" << pos->first << " value=" << pos->second << endl;
    }else{
        cout << "未找到元素" << endl;
    }

    //统计
    int num = m.count(3);
    cout << "num=" << num << endl;
    
    return 0;
}

排序

#include <iostream>
#include <map>
#include <string>
using namespace std;

class MyCompare{
public:
    bool operator()(int v1,int v2) const{
        return v1 > v2;
    }
};

void printMap(map<int,int,MyCompare> &m){
    for (map<int,int>::iterator it = m.begin();it != m.end();it++){
        cout << "key=" << it->first << " value=" << it->second << endl;
    }
}

int main() {
    map<int,int,MyCompare> m;

    m.insert(pair<int,int>(1,1));
    m.insert(pair<int,int>(2,1));
    m.insert(pair<int,int>(3,1));

    printMap(m);

    return 0;
}

函数对象

  • 函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
  • 函数对象超出普通函数的概念,函数对象可以有自己的状态
  • 函数对象可以作为参数传递
#include <iostream>
#include <string>
using namespace std;

class MyAdd{
public:
    int operator()(int v1,int v2) const{
        return v1 + v2;
    }
};

int main() {

    MyAdd myAdd;
    int num = myAdd(1,2);
    cout << num << endl;

    return 0;
}

谓词

  • 返回bool类型的仿函数称为谓词
  • 如果operator()接受一个参数,那么叫一元谓词
  • 如果operator()接受两个个参数,那么叫二元谓词
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

class GreaterFive{
public:
    bool operator()(int v1) const{
        return v1 > 5;
    }
};

int main() {

    vector<int> v;
    for (int i = 0; i < 10; ++i) {
        v.push_back(i);
    }

    vector<int>::iterator it = find_if(v.begin(),v.end(),GreaterFive());
    if (it == v.end()){
        cout << "未找到" << endl;
    } else{
        cout << *it << endl;
    }

    return 0;
}

内建仿函数

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;

void test1(){
    negate<int> n;
    cout << n(50) << endl;

    plus<int> p;
    cout << p(10,10) << endl;
}

void test2(){
    vector<int> v;
    v.push_back(2);
    v.push_back(4);
    v.push_back(3);
    v.push_back(5);
    v.push_back(1);

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

    sort(v.begin(),v.end(),greater<int>());
    for (vector<int>::iterator it =v.begin();it != v.end();it++) {
        cout << *it << " ";
    }
    cout << endl;
}

void test3(){
    vector<bool> v;
    v.push_back(true);
    v.push_back(false);
    v.push_back(true);
    v.push_back(false);

    for (vector<bool>::iterator it =v.begin();it != v.end();it++) {
        cout << *it << " ";
    }
    cout << endl;

    vector<bool> v1;
    v1.resize(v.size());
    transform(v.begin(),v.end(),v1.begin(),logical_not<bool>());

    for (vector<bool>::iterator it =v1.begin();it != v1.end();it++) {
        cout << *it << " ";
    }
    cout << endl;
}

int main() {

    //算术反函数
    test1();

    //关系仿函数
    test2();

    //逻辑仿函数
    test3();

    return 0;
}

算法

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

using namespace std;

class Person{
public:
    Person(string name, int age) {
        this->name = name;
        this->age = age;
    }
    bool operator==(const Person &p)
    {
        if (this->age == p.age)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    string name;
    int age;
};

void test1(vector<Person> v1){
    //帅选出年龄大于25的第一个对象
    vector<Person>::iterator it = find_if(v1.begin(),v1.end(),[](Person &p){
        return p.age > 25;
    });
    if (it != v1.end()){
        cout << "找到了" << endl;
        cout << "姓名:" << it->name << " 年龄:" << it->age << endl;
    }else{
        cout << "未找到" << endl;
    }
}

void test2(vector<Person> v1){
    //相邻两个对象,第一个大于第二个的年龄
    vector<Person>::iterator it = adjacent_find(v1.begin(),v1.end(),[](Person &p1,Person &p2){
        return p1.age > p2.age;
    });
    if (it != v1.end()){
        cout << "找到了" << endl;
        cout << "姓名:" << it->name << " 年龄:" << it->age << endl;
    }else{
        cout << "未找到" << endl;
    }
}

void test3(vector<int> v1){
    sort(v1.begin(),v1.end(),less<int>());
    //只能对排好序的容器进行查找
    bool  b = binary_search(v1.begin(),v1.end(),2);
    if (b){
        cout << "找到了" << endl;
    }else{
        cout << "未找到" << endl;
    }
}

void test4(vector<Person> v1,Person &p){
    //统计对象个数
    int num = count(v1.begin(), v1.end(), p);
    cout << num << endl;
}

void test5(vector<Person> v1){
    int num = count_if(v1.begin(),v1.end(),[](Person &p){
        return p.age > 25;
    });
    cout << num << endl;
}

void test6(vector<int> v1,vector<int> v2){
    vector<int> result(v1.size() + v2.size());
    std::merge(v1.begin(), v1.end(),v2.begin(),v2.end(),result.begin());
    for_each(result.begin(),result.end(),[](int num){
        cout << num << endl;
    });
}

void test7(vector<Person> v1){
    reverse(v1.begin(),v1.end());
    for_each(v1.begin(),v1.end(),[&](Person p){
        cout << "姓名:" << p.name << " 年龄:" << p.age << endl;
    });
}

void test8(){
    vector<int> source = {1, 2, 3, 4, 5};
    vector<int> destination(source.size());

    copy(source.begin(), source.end(), destination.begin());

    // 输出复制后的容器
    for (int num : destination) {
        cout << num << " ";
    }
    cout << endl;
}

void test9(){
    vector<int> source = {1, 2, 3, 4, 5};
    replace(source.begin(),source.end(),2,200);
    for (int num : source) {
        cout << num << " ";
    }
    cout << endl;
}

void test10(){
    vector<int> source = {1, 2, 3, 4, 5};
    replace_if(source.begin(),source.end(),[](int num){
        return num > 2;
    },200);

    for (int num : source) {
        cout << num << " ";
    }
    cout << endl;
}

void test11(){
    vector<int> v1 = {1, 2, 3, 4, 5};
    vector<int> v2 = {10, 20, 30, 40, 50};
    swap(v1,v2);
    for (int num : v1) {
        cout << num << " ";
    }
    cout << endl;
    for (int num : v2) {
        cout << num << " ";
    }
    cout << endl;
}

void test12(){
    vector<int> v1;
    v1.resize(10);
    fill(v1.begin(),v1.end(),100);
    for (int num : v1) {
        cout << num << " ";
    }
    cout << endl;
}

void test13(){
    cout << "test13" << endl;
    //两个源容器必须有序,且顺序一致
    vector<int> v1 = {1, 2, 3, 4, 5};
    vector<int> v2 = {3,4,5,6,7};
    vector<int> v3;
    v3.resize(min(v1.size(),v2.size()));
    vector<int>::iterator v3End = set_intersection(v1.begin(),v1.end(),v2.begin(),v2.end(),v3.begin());
    for_each(v3.begin(),v3End,[](int num){
       cout << num << endl;
    });
}

void test14(){
    cout << "test14" << endl;
    //两个源容器必须有序,且顺序一致
    vector<int> v1 = {1, 2, 3, 4, 5};
    vector<int> v2 = {3,4,5,6,7};
    vector<int> v3;
    v3.resize(min(v1.size(),v2.size()));
    vector<int>::iterator v3End = set_difference(v1.begin(),v1.end(),v2.begin(),v2.end(),v3.begin());
    for_each(v3.begin(),v3End,[](int num){
        cout << num << endl;
    });//1,2
}

void test15(){
    cout << "test15" << endl;
    //两个源容器必须有序,且顺序一致
    vector<int> v1 = {1, 2, 3, 4, 5};
    vector<int> v2 = {3,4,5,6,7};
    vector<int> v3;
    v3.resize(min(v1.size(),v2.size()));
    vector<int>::iterator v3End = set_union(v1.begin(),v1.end(),v2.begin(),v2.end(),v3.begin());
    for_each(v3.begin(),v3End,[](int num){
        cout << num << endl;
    });
}



int main()
{

    vector<Person> v1;
    Person p1("刘备", 35);
    Person p2("关羽",35);
    Person p3("张飞", 35);
    Person p4("赵云", 30);
    Person p5("曹操", 40);
    //将人员插入到容器
    v1.push_back(p1);
    v1.push_back(p2);
    v1.push_back(p3);
    v1.push_back(p4);
    v1.push_back(p5);

    for_each(v1.begin(),v1.end(),[](Person &p){
        cout << "姓名:" << p.name << " 年龄:" << p.age << endl;
    });

    //find_if
    test1(v1);

    //adjacent_find
    test2(v1);

    //binary_search
    test3({1,3,9,5,4,2});

    //count
    test4(v1,p1);

    //count_if
    test5(v1);
    cout << "--------------" << endl;

    //merge
    test6({1,3,4},{2,5,7});

    //reverse
    test7(v1);

    //copy
    test8();

    //replace
    test9();

    //replace_if
    test10();

    //swap
    test11();

    //fill
    test12();

    //交集
    test13();

    //差集
    test14();

    //并集
    test15();
    
    return 0;
}