基础语法值c++提高编程

c++的提高编程

本阶段主要针对c++泛型编程和STL技术作详细讲解,探讨c++更深层的使用

1.模板

1.1模板的概念

模板就是建立通用模具,大大提高复用性。

例如生活中的存照模板,ppt模板

模板的特点:

  • 模板不可以吧直接使用,它只是一个框架
  • 模板的通用不是万能的

1.2函数的模板

  • c++中另一种编程思想叫泛型编程,主要利用的技术就是模板
  • c++提供两种模板机制:函数模板和类模板
1.2.1函数模板的语法

函数模板作用:建立一个同样函数,其函数返回值类型类型和形参类型可以不具体指定,用虚拟类型来代表。

语法:

template

函数的声明或者定义

解释:

  • template --声明创建模板
  • typename --表明其后面的符号是一种数据类型,可以用class代替
  • T --通用数据类型参数,名称可以替换,通常为大写字母
#include<iostream>
using namespace std;
//两个整型变量交换
void intswap(int& a, int& b)
{
	int temp;
	temp = a;
	a = b;
	b = temp;
}
//两个浮点型数据交换
void doubleswap(double& a, double& b)
{
	double temp;
	temp = a;
	a = b;
	b = temp;
}
template<typename T>//声明一个模板,告诉编译器后面代码中紧跟着的T不要报错,T是一个通用的额数据类型
void myswap(T& a, T& b)
{
	T temp;
	temp = a;
	a = b;
	b = temp;
}
void test()
{
	int a = 10; int b = 20;
	//两种方式使用函数模板
	//1.自动类型推导	
	//swap(a, b);
	//cout <<a<<" " << b << endl;

	//2.显示指定类型
	myswap<int>(a, b);
	cout << a << " " << b << endl;
}	
int main()
{
	test();
	system("pause");
	return 0;
}

总结:

  • 函数模板利用关键字template
  • 使用函数模板的两种方式:自动类型推导、显示指定类型
  • 模板的目的是为了提高复用性,将类型参数化
  • 类型参数可以有多个 typename可以替换为class

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n3TmMtJp-1662911759176)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220313103452022.png)]

1.2.2函数模板的注意事项

注意事项:

  • 自动类型推导,必须推导出一致的数据类型T
  • 模板必须确定出T的数据类型才能使用
#include<iostream>
using namespace std;
template<class T>
void myswap(T& a, T& b)
{
	T temp = a;
	a = b;
	b = temp;
}
//函数模板的注意事项,
//1.自动类型的额推导,必须推导出一致的数据类型T才能使用
void test()
{
	int a = 10;
	int b = 20;
	double c = 10;
	myswap(a, b);
	//swap(a, c);错误!!!T必须对应的是相同的数据类型
	cout << a << endl;
	cout << b << endl;
}
  //2.函数模板必须要确定出T的数据类型才能使用
template<class T>
void func()
{
	cout << "你是大傻子" << endl;
}
void test02()
{
	//func();无法调用没有确定出T的数据类型
	func<int>();//确定了T的数据类型所以可以调用
}
int main()
{
	test();
	test02();
	system("pause");
}

总结:

使用模板时必须能使其确定通用的数据类型T,并且能够导出一致的数据类型

1.2.3案例:数组的排序

案例描述:

  • 封装一个排序的函数,对不同类型的数组进行排序
  • 排列规则从大到小,排序算法为选择排序
  • 分别用char数组和int数组进行测试
#include<iostream>
using namespace std;
template<class T>
void myswap(T& a, T& b)
{
	T temp = a;
	a = b;
	b = temp;
}//交换的数值的模板函数
//template <typename T>
//T mylen(T*n)
//{
//	int len = sizeof(n) / sizeof(n[0]);
//	return len;
//}
void test(char str[],int  len)//算法:选择排序
{
	for (int i = 0; i < len; i++)
	{
		int max = i;
		for (int j = i+1; j < len; j++)
		{
			if (str[max] < str[j])
			{
				max = j;
			}
		}
		if(max!=i)
		myswap(str[i], str[max]);

	}
}
template<typename T>//提供打印数组的模板
void printarr(T arr, int len)
{
	for (int i = 0; i < len; i++)
	{
		cout << arr[i] << " ";

	}
	cout << endl;
}
int main()
{	
	char arr[] = "abc";
	int len = sizeof(arr) / sizeof(arr[0]);
	test(arr, len);
	printarr(arr, len);
	system("pause");
}
1.2.4普通函数与函数模板的区别

普通函数与函数模板的区别:

  • 普通函数调用时可以发生自动类型转换(隐式转换类型)
  • 函数模板调用时,如果利用自动类型推导,不会发生隐式类型的转化
  • 如果利用显示指定类型的方式,可以发生隐式类型的转化
#include<iostream>
using namespace std;
template<class T>
int myswap(T a, T b)
{
	T temp = a;
	a = b;
	b = temp;
	return a + b;
}//交换的数值的模板函数
void test()
{
	int a=10;
	char c = 'c';
	//myswap(a, c);报错,函数模板自动类型转换不会发生隐式转化

	cout << myswap<int >(a,c) << endl;//显示指定类型能发生隐式的转换
	//注意引用不能发生隐式类型的转换 因为引用的本质就是一个指针常量
}
int main()
{	
	test();
	system("pause");
}
1.2.5普通函数和函数调用模板的规则

调用规则如下:

  • 如果函数模板和普通函数都可以实现,优先调用普通函数
  • 可以通过空模板的参数列表来强制调用函数模板
  • 函数模板也可以发生重载
  • 如果函数模板可以发生更好的匹配优先调用函数模板
#include<iostream>
using namespace std;
template<class T>
void mytest(T a, T b)
{
	cout << "函数模板的调用" << endl;
}
template<class T>
void mytest(T a, T b,T c)
{
	cout << "函数模板2的调用" << endl;
}
void mytest(int a, int b)
{
	cout << "函数的调用" << endl;
}

void test()
{
	int a = 1, b = 2, c = 1;
	char d = 'd'; char e = 'e';
	mytest(a, b);      //1.函数模板和普通函数均可以调用 优先调用函数模板
	mytest<>(a, b);    //2.添加空模板参数列表可以强制调用函数模板
	mytest<>(a, b, c); //3.函数模板也能发生重载
	mytest(d, e);      //4.如果使用模板函数可以产生更好的匹配优先模板函数(此处若是函数则还要发生隐式转化)
}
int main()
{	
	test();
	system("pause");
}

总结:在提供函数模板的前提下,最好不要提供普通函数以免出现二义性

1.2.6模板的局限性

局限性:

模板不是万能的!!

例如:拿两个类相比,函数模板不能直接实现类与类之间的比较

c++为了解决这种问题,提供模板的重载,可以为这些特定的类型提供具体化模板

#include<iostream>
using namespace std;
#include<string>
class Person
{
public:
	Person(int age,string name)
	{
		this->age = age;
		this->name = name;
	}
public:
	int age;
	string name;
};
template<typename T>
bool isyes(T& a, T& b)
{
	if (a == b)
		return true;
	else
		return false;
}
//实现具体化 显示具体化的原型和定义 以templa开头,通过名称来指出类型 (函数模板的重载)
//具体化优先于常规模板
template<> bool isyes(Person& a, Person &b)
{
	if (a.age == b.age&&a.name==b.name)
		return true;
	else
		return false;
}
void test()
{
	Person p(18, "小王");
	Person p1(20, "小吴");
	bool res = isyes(p, p1);
	if (res)
		cout << "yes" << endl;
	else
		cout << "no" << endl;
}
int main()
{	
	test();
	system("pause");
}

总结:

  • 利用具体化模板,可以解决自定义类型的通用化
  • 学习模板不是为了写模板,而是在STL能够运行系统提供的模板

1.3类的模板

1.3.1类模板的语法

类模板的作用:

  • 建立一个通用类,类中的成员数据类型可以不具体制定,用一个虚拟的类型来代表
#include<iostream>
using namespace std;
#include<string>
template<class Typename,class Age>//模板参数可以为多个
class Person
{public:
	Person(Typename name, Age age)
	{
		this->age = age;
		this->name = name;
	}
public:
	Typename name;
	Age age;
};
void test()
{
	string s = "你好啊";
	int age = 18;
	Person<string, int> p(s, age);//指定类型
	cout << p.age << p.name << endl;
}
int main()
{
	test();
	system("pause");
}

总结:函数模板和类模板十分的相似 在template后面加类 此类称为类模板

1.3.2类模板与函数模板的区别

主要区别有两点:

  • 类模板中没有自动类型推导的公式
  • 类模板在参数列表中可以有默认参数
#include<iostream>
using namespace std;
template<class Nametype,class Agetype=int>//类模板在参数列表中有默认的参数
class Person
{
public:
	Person(Nametype age, Agetype name)
	{
		this->age = age;
		this->
	}
public:
	Nametype name;
	Agetype age;

};
void test()
{
	//Person<> p("bs", 188);不能这样子写 类模板中没有自动推导类型
	Person<string>p("nishi", 188);//因为指定了第二个参数是一个默认参数 所以此处可以不指定第二个参数的类型
}
int main()
{
	test();
	system("pause");
}

总结:

  • 类模板中只能用显示指定类型的方式
  • 类模板的模板参数列表可以有默认参数
1.3.3类模板中函数的创建时机

类模板中的成员函数和普通类中的成员函数创建时机是有区别的:

  • 普通类中成员函数一开始就创建
  • 类模板成员函数在调用时才创建
#include<iostream>
using namespace std;
class Person1
{
public:
	void showperson1()
	{
		cout << "1" << endl;
	}
};

class Person2
{
public:
	void showperson2()
	{
		cout << "1" << endl;
	}
};
template <class T>
class Mymoban
{
	//类模板中的成员函数 并不是一开始就创建的,而是模板调用时在产生
; public:
	T p;
	void func1()
	{
	p.showperson1();
	}
	void func2()
	{
	p.showperson2();
	}
};
void test()
{
	Mymoban<Person1> m;
	m.func1();
	//m.func2();报错!!指定类型为person1
}
int main()
{
	test();
	system("pause");
}

总结:类模板成员函数并不是一开始就被创建的,在调用时才被创建

1.3.4类模板对象作函数参数

类模板实例化出的对象,向函数传参的方式,一共有三种传入方式:

  • 指定传入类型–直接显示对象的数据类型
  • 参数模板化–将对象中的参数变为模板进行传递
  • 整个类模板化-- 将这个对象类型模板化进行传递
#include<iostream>
using namespace std;
template <class T1,class T2>
class Person
{
public:
	Person(T1 age, T2 name)
	{
		this->age = agel
		this->name = name;
	}
	void showperson()
	{
		cout << age << name << endl;
	}
public:
	T1 age;
	T2 name;
};
//1.指定传入类型
void printperson(Person<int,string>&p)
{
	p.showperson();
}
//2.参数模板化 
template<class T1,class T2>
void printperson2(Person<T1,T2>&p)
{
	p.showperson();
}
//3.整个类模板化
template<class T>
void printperson3(T& p)
{
	p.showperson();
	cout << "T的数据类型是:" << typeid(T).name() << endl;//查看编译器推导出来的类型
}

void test()
{
	Person<int ,string> p(19, "雄安王");
	printperson(p);
}

int main()
{
	test();
	system("pause");
}

总结:

  • 通过类模板创建对象,可以有三种方式向函数中进行传参
  • 比较广泛的是第一种:指定传入类型
1.3.5类模板与继承

当类模板碰到继承的时候,需要注意以下几点:

  • 当子类继承父类中的一个模板时,子类在声明的时候,要指出父类中的T类型
  • 如果不指定编译器无法给子类分配内存
  • 如果想灵活指出父类中的T的类型,子类也需要变模板
#include<iostream>
using namespace std;
template <class T>
class Base
{
public:
	T a;
};
class Son :public Base<int>//必须指定一个类型 因为c++要给子类分配内存 必须知道父类中的T的类型才能往下继承
{

};
void test01()
{
	Son s;
}
//如果想灵活指定父类中T的 类型,子类也需要变模板
template <class T1,class T2>
class Son2 :public Base<T1>
{
public:
	Son2()
	{
		cout << "T1的类型为" << typeid(T1).name() << endl;
		cout << "T2的类型为" << typeid(T2).name() << endl;
	}
	T2 a;

};
void test02()
{	
	Son2<int ,char> s1;
}
int main()
{
	test01();
	test02();
	system("pause");
}

总结:灵活变通。

1.3.6类模板成员函数类外实现
#include<iostream>
using namespace std;
template <class T1, class T2>
class Person
{
public:
	Person(T1 name, T2 age);
	//{
	//	this->age = age;
	//	this->name = name;
	//}
	void showmessage();
	//{
	//	cout << age << endl;
	//	cout << name << endl;
	//}
	T1 name;
	T2 age;
};
//类外实现 注意比较个普通类的类外实现的区别 
template <class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age)
{
	this->age = age;
	this->name = name;
}
template <class T1, class T2>
void Person<T1, T2>::showmessage()
{
	cout << age << endl;
	cout << name << endl;
}
int main()
{
	system("pause");
}

总结:类模板中成员函数类外实现,需要加上模板参数列表。

1.3.7类模板分文件编写

掌握类模板成员函数分文件编写产生的问题及解决方式

问题:

  • 类模板中的成员函数创建时机是在调用阶段,导致份文件编写时链接不到

解决:

  • 直接包含.cpp文件
  • 将声明和实现写在同一个文件中,并更改后缀名为.hpp,hpp是约定的名称并不是强制的,工程上一般采用这种方法
modle.hpp:
#include<iostream>
using namespace std;
template <class T,class T2>   //类模板的声明和实现
class Person
{
public:
	void outt(T a, T2 b);
public:
	T age;
	T2 name;
};
template <class T, class T2>
void Person<T, T2>::outt(T a, T2 b)
{
	cout << "你好啊" << endl;
}

main.cpp:
    
#include"modle.hpp"
using namespace std;

int main()
{
	Person<int, int> p;
	p.outt(10,10);
	system("pause");
}
1.3.8类模块与友元

学习目标:

  • 掌握类模板配合友元函数的类内和类外实现

全局函数类内实现-直接在类内声明友元即可

全局函数类外实现-需要提前让编译器知道全局函数的存在

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

//提前让编译器知道Person类的存在
template <class T1,class T2>
class Person;

//类外实现
template <class T1, class T2>
void showperson(Person<T1, T2>& p)//这是一个函数模板的参数
{ 
	cout << "类外实现的名字是:" << p.name << "年龄是:" << p.age;
}
template <class T1,class T2>

class Person
{
//类内的全局函数
//	friend void showperson(Person<T1, T2>& p);
//{
//	cout << "名字是:" << p.name << "年龄是:" << p.age;
//}


//类外实现全局函数
//如果全局函数是类外实现的话,需要让编译器提前知道这个函数的存在
	friend void showperson <>(Person<T1, T2>& p);//加空模板参数实现 因为外面实现的是一个函数模板
public:
	Person(T1 name, T2 age)
	{
		this->age = age;
		this->name = name;
	}
private:
    T1 name;
	T2 age;
};

void test()
{   

	Person<string, int> p("王仁鑫", 18);
	showperson(p);
}

int main()
{
	test();
	system("pause");
}

总结:建议类内实现 编译器好识别,类外实现太过繁杂

2.初识STL!

2.1STL的诞生
  • 软件希望建立可以一直复用的模板
  • c++面向对象和泛型编程思想,目的就是复用性的提升
  • 大多情况下,数据结构和算法都未能拥有一套标准,导致被迫从事大量的工作
  • 为了建立数据结构和算法的一套标准,诞生了STL
2.2STL的基本概念
  • STL标准模板库(STAND TEMPLATE LIBRARY)
  • STL广义上分为:容器 算法 迭代器
  • 容器和算法之间通过迭代器相连
  • STL几乎所有代码都采用了模板类或者模板函数
2.3STL六大组件

六大组件分别是:容器 算法 迭代器 仿函数 适配器 空间配置器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L3e1SZAq-1662911759178)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220319142952524.png)]

2.4容器、算法、迭代器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SiCDigMv-1662911759178)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220319143131627.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r53AUOLh-1662911759179)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220319143239714.png)]

迭代器的使用十分类似指针

迭代器的种类:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7yNl8eBp-1662911759179)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220319143650775.png)]

2.5容器算法迭代器的初识

STL中做常用的容器为vector,可以理解为数组

2.5.1vector存放内置数据类型

容器:vector

算法:for_each

迭代器:vector::iterator

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>//algorrithm是算法的意思
void myprit(int val)
{
	cout << val << endl;
}
void test()
{//创建容器对象,并且通过模板参数指定容器中存放的数据类型
	vector<int> v;//a
	//向容器中放数据
	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	//每一个容器都有自己的迭代器 迭代器用来遍历数组中的元素
	//v.begin() 返回的是一个迭代器 这个迭代器指向的是容器中的第一个数据
	//v.end() 返回的是一个迭代器 这个迭代器指向的数组中最后一个元素的后一位
	//vector<int>::iterator 拿到vector<int>这种容器迭代器的类型
	vector<int>::iterator pbegin = v.begin();//iterator 是迭代器的意思
	vector<int>::iterator pend = v.end();
	//第一种遍历方式
	while (pbegin != pend)
	{
		cout << *pbegin << endl; 	
		pbegin++;
	}
	//第二种遍历方式
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << endl;
	}
	//第三种遍历方式
	//使用stl提供的标准遍历算法 头文件algorithm
	for_each(v.begin(), v.end(), myprit);//写一个函数名 回调

}
int main()
{
	test();
	system("pause");
}
2.5.2vector存放自定义数据类型
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>//algorrithm是算法的意思
class Person
{
public:
	Person(int age,string name)
	{
		this->age = age;
		this->name = name;
	}
public:
	int age;
	string name;
};
void test()
{
	Person p1(18, "小王");
	Person p2(19, "小王");
	Person p3(12, "小王");
	Person p4(14, "小王");
	vector<Person*>v;
	v.push_back(&p1);
	v.push_back(&p2);
	v.push_back(&p3);
	v.push_back(&p4);
	for(vector<Person*>::iterator t=v.begin();t!=v.end();t++)//t可以看作指向存储元素的指针
	{
		cout << "名字是" << (*t)->name << "年龄是:" << (*t)->age << endl;

	 }
}
void test02()
{
	Person p1(18, "小王");
	Person p2(19, "小王");
	Person p3(12, "小王");
	Person p4(14, "小王");
	vector<Person>v;
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	for (vector<Person>::iterator t = v.begin(); t != v.end(); t++)
	{
		cout << "名字是" << t->name << "年龄是:" << t->age << endl;

	}
}
int main()
{
	test02();
	test();
	system("pause");
}
2.5.3vector容器中嵌套容器
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>//algorrithm是算法的意思
void test()
{
	vector<vector<int>> v;
	vector<int> v1;
	vector<int> v2;
	vector<int> v3;
	vector<int> v4;
	for (int i = 0; i < 5; i++)
	{
		v1.push_back(i);
		v2.push_back(i+1);
		v3.push_back(i+2);
		v4.push_back(i+3);
	}
	v.push_back(v1);
	v.push_back(v2);
	v.push_back(v3);
	v.push_back(v4);
	for (vector<vector<int>>::iterator it = v.begin(); it != v.end(); it++)//*it指的是vector<int>容器  此处可以理解为二维数组

	{
		for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++)//每一个容器都有对应的迭代器
		{
			cout << *vit << " ";      
		}
		cout << endl;
	}
}
int main()
{
	
	test();
	system("pause");
}

3.STL常用容器

3.1string
3.1.1string的基本概念

本质:

string的本质是一个类

string和char*的区别:

  • char*是一个字符指针
  • string是一个类, 类内封装了char**,管理这个字符串,是一个char*的容器

特点:

string类内封装了很多成员的方法

例如:find查找,copy复制,删除delete,替换replace,插入insert

string管理char*分配的内存,不用担心越界的问题,由类内部进行负责

3.1.2string的构造函数

构造函数原型:

  • string();创建一个空字符串 例如:string str;
  • string(const char* s);//使用字符串s初始化
  • string(const string&str);拷贝构造 使用一个string对象初始化另一个string对象
  • string(int n,char c) 使用n个字符c初始化
#include<iostream>
using namespace std;
#include<vector>
#include<string>
#include<algorithm>//algorrithm是算法的意思
//- string(); 创建一个空字符串 例如:string str;
//- string(const char* s);//使用字符串s初始化
//-string(const string & str); 拷贝构造 使用一个string对象初始化另一个string对象
//- string(int n, char c) 使用n个字符c初始化

void test()
{
	string str;
	const char* s = "sbhajdb";
	string s1(s);
	cout << s1 << endl;
	string s2(s1);
	cout << s2 << endl;
	string s3(5, 'c');
	cout << s3 << endl;
}
int main()
{
	
	test();
	system("pause");
}

总结:灵活使用!

3.1.3string的赋值操作

赋值函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FnQdHTFT-1662911759180)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220320102955999.png)]

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


void test()
{
	string str = "hellow";
	string str1 = str;
	string str2 = "c";
	string str3;
	str3.assign("bshadb");
	string str4;
	str4.assign("hellow c++", 5);
	string str5;
	str5.assign(str4);
	string str6;
	str6.assign(5, 'c');
	cout << str6 << endl;
}
int main()
{
	test();
	system("pause");
}
3.1.4string的拼接操作

函数模型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CkQ6LmN8-1662911759180)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220320140019585.png)]

#include<iostream>
using namespace std;
#include<string>
void test()
{
	string str = "i love ";
	string str2 = "game";
	string str3=" ";
	str3 += str += str2;
	str3 += 'd';
	str3 += " LOL";
	cout << str3<< endl;

	string str4=" ";
	str4.append("你好啊");
	str4.append("美女啊",2);
	string str5 = "一起玩游戏吗";
	str4.append(str5);
	string str6 = "球球了";
	str4.append(str6, 0, 3);//参数二是你想从哪个位置开始截取  参数三是截取的字符个数
	cout << str4 << endl;

}
int main()
{
	test();
	system("pause");
}

注意:

  • 字符串字面值并不是string对象

  • 进行+运算时+号两侧的对象至少有一个是string

3.1.5string的查找和替换的操作

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OcmWppPk-1662911759181)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220320143339102.png)]

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

//查找
void test()
{
	string a="abcdefa";
	int pos=a.find("cd");
	cout << pos << endl;
	pos = a.find('s', 4);
	cout << pos << endl;
	string b = "f";
	pos = a.find(b);
	cout << pos << endl;
	//find和rfind的区别是 一个是从左往右找 一个是从右往左找
	pos=a.rfind('a');
	cout << pos << endl;
	pos = a.find('a');
	cout << pos << endl;
}
//替换
void test2()
{
	string str;
	str = "abcda";
	str.replace(1, 1, "bbbbbb");//第一个位置的字符开始后的一个字符 替换为”bbbbbb“
	cout <<str << endl;
}
int main()
{
	test();
	test2();
	system("pause");
}
3.1.6字符串的比较

比较方式

  • 字符串的比较是按照字符的acsll码进行对比的

等于返回0

大于返回1

小于返回-1

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

//查找
void test()
{
	string str = "hellow";
	string str2 = "aellow";
	int res=str.compare(str2);
	cout << res << endl;
}
int main()
{
	test();

	system("pause");
}
3.1.7字符串的存取

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DizL8eSf-1662911759181)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220320151541962.png)]

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

void test()
{	
	string s = "hellow";
	for (int i = 0; i < s.size(); i++) //size()函数返回字符串的大小、
	{
		cout << s[i];
	}
	cout << endl;
	for (int i = 0; i < s.size(); i++) //size()函数返回字符串的大小、
	{
		cout << s.at(i);
	}
	cout << endl;
	//修改
	s[2] = 'a';
	s.at(3) = 'a';
}
int main()
{
	test();
	system("pause");
}

总结:string单个字符存取方式有两种 一个是[]一个是at()

3.1.8字符串的插入和删除

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VKjsZtuv-1662911759182)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220320155616919.png)]

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

void test()
{
	string s = "hellow";
	s.insert(1, "111");
	cout << s << endl;
	string s2 = "123";
	s.insert(3, s2);
	cout << s << endl;

	s.erase(1, 3);//删除从第一个位置开始 三个字符
	cout << s << endl;
}
int main()
{
	test();
	system("pause");
}

总结:c++数组起始下标是0

3.1.9字符串的子串

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-456IrXyr-1662911759182)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220320160129160.png)]

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

void test()
{
	string s = "hellow";
	string s2=s.substr(0, 5);
	cout << s2 << endl;
}
//实例
void test02()
{
	string qq = "jdbasjbd@qq.com";
	qq.find('@');
	string qq_name = qq.substr(0, qq.find('@'));//从第零个位置开始 qq.find('@')个字符组成的字符串
	cout << qq_name << endl;
}
int main()
{
	test();
	test02();
	system("pause");
}
3.2vector容器
3.2.1vector容器的基本概念

功能:

  • vector数据结构和数组十分相似,也成为单端数组

vector和普通数组的区别:

  • 不同之处在于数组是静态空间,而vector可以动态扩展(通过关键字)

动态扩展:

  • 并不是在原空间之后续新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iOvOZhqz-1662911759183)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220322193734838.png)]

  • vector容器迭代器是支持随机访问的迭代器
3.2.2vector构造函数

功能描述:

  • 创建vector容器

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QLXjPyZ0-1662911759183)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220322194159961.png)]

#include<iostream>
#include<vector>
using namespace  std;
void P_vector(vector<int>(&v))
{
    for(vector<int>::iterator it=v.begin();it!=v.end();it++)
    {
        cout<<*it<<" ";
    }
}

int main()
{
    vector<int>v;
    v.push_back(10);
    v.push_back((20));
    v.push_back((30));
    vector<int>::iterator it;
    for(it=v.begin();it!=v.end();it++)
    {
        cout<<*it<<endl;
    }
    vector<int>v1(v.begin(),v.end());
    P_vector(v1);
    vector<int>v2(v1);
    P_vector(v2);
    vector<int>v3(5,0);
    system("pause");
    return  0;
}
3.2.3vector容器的赋值操作

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DaLIhrTx-1662911759184)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220322200934896.png)]

#include<iostream>
#include<vector>
using namespace  std;
void P_vector(vector<int>(v))
{
    for(vector<int>::iterator it=v.begin();it!=v.end();it++)
    {
        cout<<*it<<" ";
    }
}
int main()
{
    vector<int>v;
    v.push_back(10);
    v.push_back((20));
    v.push_back((30));
    vector<int>v2=v;
    P_vector(v);
    vector<int>v3;
    v3.assign(3,100);
    P_vector(v3);
    vector<int>v4;
    v4.assign(v.begin(),v.end());
    P_vector(v4);
    return  0;
}
3.2.4vector的容量和大小

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YwxL8YqJ-1662911759184)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220322202219743.png)]

#include<iostream>
#include<vector>
using namespace  std;
void P_vector(vector<int>(v))
{
    for(vector<int>::iterator it=v.begin();it!=v.end();it++)
    {
        cout<<*it<<" ";
    }
}
int main()
{
    vector<int>v;
    v.push_back(10);
    v.push_back((20));
    v.push_back((30));
   if(v.empty()) {
       cout << "yes" << endl;
   }
   else {
       cout << "\n" << v.capacity() << endl;
       cout << v.size() << endl;
       v.resize(2,0);//重新指定size的大小 并且多余的用0来补充 若比原来的改变的size比原来的小 不会改变capacity的大小
       cout<<v.capacity()<<endl;
       P_vector(v);
   }
    return  0;
}
3.2.5vector的插入和删除

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WWncbSrd-1662911759185)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220322204859731.png)]

#include<iostream>
#include<vector>
using namespace  std;
void P_vector(vector<int>(v))
{
    for(vector<int>::iterator it=v.begin();it!=v.end();it++)
    {
        cout<<*it<<" ";		
    }
}
int main()
{
    vector<int>v;
    //尾插法
    v.push_back(10);
    v.push_back((20));
    v.push_back((30));
    P_vector(v);
    //尾删法
    v.pop_back();
    v.pop_back();
    P_vector(v);
    //插入
    v.insert(v.begin(),100);
    P_vector(v);
    v.insert(v.begin(),5,100);
    P_vector(v);
    //删除
    v.erase(v.begin());
    P_vector(v);
    v.erase(v.begin(),v.end());//删除所有元素
    //删除所有元素
    v.clear();
    return  0;
}
3.2.6vector的数据存取

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lc1TfJeJ-1662911759185)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220322210417143.png)]

int main()
{
    vector<int>v;
    //尾插法
    v.push_back(10);
    v.push_back((20));
    v.push_back((30));
    //通过下标访问
    v[0]=11;
    //通过at访问
    v.at(0)=12;
    //返回第一个元素
    v.front();
    //返回最后一个元素
    v.back();
    return  0;
}
3.2.7vector互换容器

​ 功能:

  • 实现两个容器元素进行交换

函数原型:

  • swap(v);//将v与本身的元素互换
#include<iostream>
#include<vector>
using namespace  std;
void P_vector(vector<int>(v))
{
    for(vector<int>::iterator it=v.begin();it!=v.end();it++)
    {
        cout<<*it<<" ";
    }
}
int main()
{
    //交换两个容器的元素
    vector<int>v;
    v.push_back(10);
    v.push_back((20));
    v.push_back((30));
    vector<int>v1;
    v1.push_back(30);
    v1.push_back(20);
    v1.push_back(10);
    v.swap(v1);
    P_vector(v);
    //利用swap来收缩内存
    vector<int>v3(10000);
    cout<<v3.size()<<" "<<v3.capacity()<<endl;
    v3.resize(3);
    vector<int>(v3).swap(v3);//vector<int>(v3) 是一个调用拷贝构造拷贝v3的匿名对象(v3已经改变大小),用匿名对象与v3做交换,匿名对象作用完这一行就会消失
    cout<<v3.size()<<" "<<v3.capacity();//此时v3和匿名对象已经交换了 大小已经改变了
    return  0;
}

总结:

swap能来交换两个容器的元素,切利用匿名对象来收缩内存。交换容器会改变原来的大小和容量

3.2.8利用reserve预留空间

功能描述:

  • 减少vector在动态扩展容量时的扩展次数

函数原型:

  • reserver(int len);//容器预留len个元素长度,预留位置不初始化,元素不可访问。
#include<iostream>
#include<vector>
using namespace  std;
int main()
{
    vector<int> v;
    v.reserve(10000);//预留空间 减少v在自动扩展容量时的次数
    int num=0;
    int *p= nullptr;

    for(int i=0;i<10000;i++)
    {
        v.push_back(i);
        if(p!=&v[0])
        {
            num++;//记录容量扩展的次数
            p=&v[0];
        }
    }
    cout<<num<<endl;

    return  0;
}

总结:如果数据量够大可以在一开始就预留空间。

3.3deque容器
3.3.1deque的基本概念

功能:

  • 双端数组,可以对头端进行插入删除操作

deque与vector的区别:

  • vector对于头部插入的删除效率低,数据量越大效率越低
  • deque相对而言,对头部的插入和删除速度比vector快
  • vector访问元素的时候速度会比deque快,这和两者的内部实现有关

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kRQjeX9C-1662911759186)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220326114712007.png)]

deque的工作原理:

deque内部有个中控器,维护每段缓存区的内容,缓冲区中存放真实数据,中控器维护的时每个缓冲区的地址,使得使用deque时像一片连续的内存空间。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q5QjQ3LE-1662911759186)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220326114914975.png)]

  • deque支持随机访问。
3.3.2构造函数

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EkTYHvtR-1662911759186)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220326115514521.png)]

#include<iostream>
#include<deque>
using namespace  std;
void printfde(const deque<int> &d )//顶层const不允许函数内修改	
{
    for(deque<int>::const_iterator it=d.begin();it!=d.end();it++)
    {
        cout<<*it<<endl;
    }

}
int main()
{
    deque<int> d;                   //默认构造
    d.push_back(10);
    d.push_back(20);
    printfde(d);
    deque<int>d1(d.begin(),d.end());//传入迭代器区间的有参构造函数
    printfde((d1));
    deque<int>d3(5,100);            //指定n个数的有参构造
    printfde(d3);
    deque<int>d4(d3);               //拷贝构造
    printfde(d4);
    return 0;
}

3.3.3deque的赋值方式

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-diMRP9tO-1662911759187)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220326132217595.png)]

#include<iostream>
#include<deque>
using namespace  std;
void printfde(const deque<int> &d )
{
    for(deque<int>::const_iterator it=d.begin();it!=d.end();it++)
    {
        cout<<*it<<endl;
    }

}
int main()
{
    deque<int> d;//默认构造
    d.push_back(10);
    d.push_back(20);
    deque<int>d2=d;
    printfde(d2);
    deque<int>d3;
    d3.assign(d2.begin(),d2.end());
    printfde(d3);
    deque<int>d4;
    d4.assign(4,100);
    printfde(d4);
    return 0;
}

3.3.4deque的大小操作

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MeplFW4A-1662911759187)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220326132649324.png)]

#include<iostream>
#include<deque>
using namespace  std;
void printfde(const deque<int> &d )
{
    for(deque<int>::const_iterator it=d.begin();it!=d.end();it++)
    {
        cout<<*it<<endl;
    }
}
int main()
{
    deque<int> d;//默认构造
    d.push_back(10);
    d.push_back(20);
    d.push_back(10);
    d.push_back(20);
    d.push_back(10);
    d.push_back(20);
    if(d.empty())
        return 0;
    else
    {
        cout<<"不会为空"<<endl;
        cout<<d.size()<<endl;//没有容量的概念 与本身的结构有关系
        printfde(d);
        d.resize(10,0);
        printfde(d);
        d.resize(3);
        printfde(d);
    }
    return 0;
}

3.3.5deque的插入和删除数据

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rmVMwcCe-1662911759187)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220326135405448.png)]

#include<iostream>
#include<deque>
using namespace  std;
void printfde(const deque<int> &d )
{
    for(deque<int>::const_iterator it=d.begin();it!=d.end();it++)
    {
        cout<<*it<<" ";
    }
    cout<<endl;

}
int main()
{
    deque<int> d;//默认构造
    //两端插入删除操作
    d.push_back(10);
    d.push_back(20);
    d.push_front(1);
    d.push_front(2);

    d.pop_back();
    d.pop_front();
    printfde(d);
    //insert插入
    deque<int>d2;
    d2.insert(d2.begin(),1);
    d2.insert(++d2.begin(),5,2);
    printfde(d2);
    d2.insert(d2.begin(),d2.begin(),d2.end());
    printfde(d2);
    //erase删除操作
    d2.erase(d2.begin());
    printfde(d2);
    d2.erase(d2.begin(),d2.end());
    printfde(d2);
    //清空操作
    d2.clear();
    return 0;
}

3.3.6deque数据存取

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eBvCzWhO-1662911759188)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220326140335778.png)]

#include<iostream>
#include<deque>
using namespace  std;
int main()
{
    deque<int> d;//默认构造
    //两端插入删除操作
    d.push_back(10);
    d.push_back(20);
    d.push_front(1);
    d.push_front(2);
    cout<<d[0]<<endl;
    cout<<d.at(1)<<endl;
    cout<<d.front()<<endl;
    cout<<d.back()<<endl;
    return 0;
}

3.3.7deque的排序

功能描述:

利用算法实现对deque容器进行排序

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-erFf5HCc-1662911759188)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220326140833332.png)]

3.4评委打分案例

简单说明:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oI072mPP-1662911759188)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220327014452152.png)]

#include<iostream>
#include<string>
#include<deque>
#include<vector>
#include<algorithm>
#include<ctime>
using namespace std;
//选手的类
class Person
{
public:
	Person(string name, int score) :name(name), score(score)
	{

	}
public:
	string name;
	int score;
};
//创建选手
void creatPerson(vector<Person>&v)
{
	string nameseed = "ABCDE";
	for (int i=0;i<5;i++)
	{
		string name = "选手";
		int score = 0;
		name += nameseed[i];
		Person p(name, score);
		v.push_back(p);
	}
}
//打分
void setscoreAndshow(vector<Person>& v)
{
	for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
	{
		deque<int>d;//将评委分数放入deque中
		for (int i = 0; i < 10; i++)
		{
			int score = rand() % 41 + 60;//60-100的随机数
			d.push_back(score);
		}
		//进行排序 升序
		sort(d.begin(), d.end());
		//删掉最高分和最d
		d.pop_back();
		d.pop_front();
		int sum = 0;
		for (deque<int>::iterator dt=d.begin(); dt != d.end(); dt++)
		{
			sum += *dt;
		}
		int everage = sum / d.size();
		(*it).score = everage;
		cout << "选手:" << it->name << " " << "分数:" << it->score << endl;
	}
}
int main()
{
	//随机数种子
	srand((unsigned int)time(NULL));
	vector<Person>v;
	creatPerson(v);
	setscoreAndshow(v);
	system("pause");
}

3.5stack容器
3.5.1栈的基本概念

概念:栈是一个后进先出的数据结构,它只有一个出口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-85dwKV51-1662911759189)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220327095407586.png)]

注意:

  • 栈中只有顶部元素可以被外界访问到,因此栈不允许有遍历的行为。
  • 数据的出入称为 出栈和入栈。
3.5.2stack的常用接口

功能:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GJW1RxAi-1662911759189)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220327095721910.png)]

#include<iostream>
#include<stack>
using namespace  std;
int main()
{
    stack<int>s;
    s.push(10);
    s.push(23);
    s.push(30);
    s.push(40);
    while(!s.empty())
    {
        cout<<s.size()<<endl;
        cout<<s.top()<<endl;
        s.pop();
    }
    stack<int>s2(s);
    stack<int>s3=s2;
    return  0;
}
3.6queue容器
3.6.1queue的基本概念

概念:

队列是一个先进先出的数据结构,他有两个出口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7e0x6xHm-1662911759190)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220327101842646.png)]

注意:

  • 队列只允许在一端新增数据,在另一端删除数据
  • 队列中只有队头和队尾才能被外界使用,因此队列不允许有遍历的行为
  • 数据的出入叫进入队和出队
3.6.2队列的常用接口

功能:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mahvX66Q-1662911759190)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220327102449873.png)]

#include<iostream>
#include<queue>
#include<string>
using namespace std;
class Person
{
public:
    Person(string name, int age) {
        this->name = name;
        this->age = age;
    }
public:
    string name;
    int age;
};
int main()
{
    Person p1("唐僧", 30);
    Person p2("孙悟空", 60);
    Person p3("猪八戒", 40);
    Person p4("沙僧", 90);
    queue<Person>q;
    q.push(p1);
    q.push(p2);
    q.push(p3);
    q.push(p4);
    while (!q.empty())//先进先出 后进后出
    {
        //访问队头
        cout << q.front().name << " " << q.front().age<<endl;
        //访问对尾
        cout << q.back().name << " " << q.back().age<<endl;
        q.pop();
    }
    cout << q.size() << endl;
    system("pause");
}
3.7list容器
3.7.1list的基本概念

功能:

将数据进行链式存储

链表的组成:链表由一系列结点组成

节点的组成:一个存储数据元素的数据域,另一个是存储数据的指针域

STL中的链表是一个双向链表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mFO8rzeo-1662911759191)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220328220416741.png)]

优缺点:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j4XrqueS-1662911759191)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220328220629813.png)]

3.7.2list的构造函数

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eERrLIoa-1662911759191)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220328234903917.png)]

#include<iostream>
#include<list>
#include<string>
using namespace std;
void printfg(list<int>&l)
{
    for(list<int>::iterator it=l.begin();it!=l.end();it++)
    {
        cout<<*it<<" ";
    }
    cout<<endl;
}
void test01()
{
    list <int >l;//默认构造
    l.push_back(10);
    l.push_back((20));
    list<int>l2(l);//拷贝构造
    list<int>l3(l.begin(),l.end());//将区间的元素拷贝给本身
    list<int>l4(5,100);//将n个value拷贝给本身
    printfg(l);
    printfg(l2);
    printfg(l3);
    printfg(l4);
}

int main()
{
test01();
}
3.7.3list的赋值和交换

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZybdeVwA-1662911759192)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220328235908847.png)]

#include<iostream>
#include<list>
#include<string>
using namespace std;
void printfg(list<int>&l)
{
    for(list<int>::iterator it=l.begin();it!=l.end();it++)
    {
        cout<<*it<<" ";
    }
    cout<<endl;
}
void test01()
{
    list <int >l;//默认构造
    l.push_back(10);
    l.push_back((20));
    printfg(l);
    list<int>l2=l;
    printfg(l2);
    list<int>l3;
    l3.assign(l.begin(),l.end());
    printfg(l3);
    l3.assign(8,100);
    printfg(l3);
    l3.swap(l2);
    printfg(l3);
}

int main()
{
test01();
}
3.7.4list的大小操作

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L9mO6d2O-1662911759192)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220329134309689.png)]

#include<iostream>
#include<list>
#include<string>
using namespace std;
void printfl(list<int>&l)
{
    for(list<int>::iterator it=l.begin();it!=l.end();it++)
    {
        cout<<*it<<" ";
    }
    cout<<endl;
}
int main()
{
    list<int>l;
    l.push_back(10);
    l.push_back(29);
    l.push_back(30);
    printfl(l);
    cout<<l.size()<<endl;
    if(!l.empty())
    {
        l.resize(2);
        printfl(l);
        l.resize(8,1000);
        printfl(l);
    }
    return 0;
}
3.7.5list的插入和删除

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LpLgkC0D-1662911759193)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220329135433135.png)]

3.7.6list的数据存取

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zcAciDri-1662911759193)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220329135533911.png)]

3.7.7list的反转和排序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FUVPLSFM-1662911759193)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220329144100953.png)]

#include<iostream>
#include<list>
#include<string>
using namespace std;
bool myconpare(int v1,int v2)//z
{//降序就让第一个数>第二个数
    return v1>v2;
}
void printfl(list<int>&l)
{
    for(list<int>::iterator it=l.begin();it!=l.end();it++)
    {
        cout<<*it<<" ";
    }
    cout<<endl;
}
int main()
{
    list<int>l;
    l.push_back(10);
    l.push_back(29);
    l.push_back(20);
    printfl(l);
    l.reverse();//反转
    printfl(l);	
/*    sort(l.begin(),l.end());//会报错 不支持随机访问的迭代器不能使用标准算法*/
    l.sort();//这是容器内部成员函数自定义的sort函数 从小到大升序
    printfl(l);		
    l.sort(myconpare);//传入自己设置的降序函数名s之变为降序 
    printfl(l);
    return 0;
}
3.7.8list的排序案例
#include<iostream>
#include<list>
#include<string>
using namespace std;
class Person
{
public:
    Person(string name, int age, int height) :name(name), age(age), height(height)
    {
    }
public:
    string name;
    int age;
    int height;
};
void printfl(list<Person>& l)
{
    for (list<Person>::iterator it = l.begin(); it != l.end(); it++)
    {
        cout << (*it).name << " " << (*it).age << " " << (*it).height << endl;
    }
    cout << endl;
}
bool mysort(Person& p, Person& p1)//回调函数 自定义类型排序的设定
{
    if (p.age == p1.age)
        return p.height < p1.height;
    return p.age < p1.age;
}
int main()
{
    list<Person>l;
    Person p1("A", 15, 188);
    Person p2("B", 119, 180);
    Person p3("C", 16, 189);
    Person p4("D", 16, 180);
    printfl(l);
    l.push_back(p1);
    l.push_back(p2);
    l.push_back(p3);
    l.push_back(p4);
    l.sort(mysort);
    printfl(l);
    system("pause");
}

3.8set/multiset容器
3.8.1set的基本概念

简介:

  • 所有元素都会在插入时自动排序

本质:

  • set/multiset属于关联式容器,底层结构是二叉树实现的(红黑树)

set和multiset的区别:

  • set不允许容器中由重复的元素
  • multise允许容器中由重复的元素
3.8.2set构造和赋值

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-unFYmtqa-1662911759194)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220412210439416.png)]

#include<iostream>
#include<set>
using namespace std;
void Printf(set<int>&s)
{
    for(auto i=s.begin();i!=s.end();++i)
    {
        std::cout<<*i<<" ";
    }
    cout<<endl;
}
int main()
{
    set<int>s;
    //set容器只有insert这一种插入数据的方式
    s.insert(20);
    s.insert(30);
    s.insert(10);
    s.insert(30);
    //set容器不允许插入重复值
    //set容器的特点所有元素插入时自动排序
    Printf(s);
    set<int>s2(s);
    Printf(s2);
    set<int>s3;
    s3=s2;
    Printf(s3);
}
3.8.3set容器大小和交换

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NdjUBpV5-1662911759194)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220412212441445.png)]

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XoSRkAZJ-1662911759194)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220412212630364.png)]

3.8.4set容器的查找和统计

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yaUBsJHu-1662911759195)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220412212827305.png)]

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

    int main()
    {
        set<int>s;
        //set容器只有insert这一种插入数据的方式
        s.insert(20);
        s.insert(30);
        s.insert(10);

        //查找元素
        auto t=s.find(20);
        if(t!=s.end())
        {
            cout<<"找到啦"<<*t<<endl;
        }
        else
        {
            cout<<"没有找到"<<endl;
        }
        //同级元素
        auto y=s.count(20);//返回0或者1
        if(y)
        {
            cout<<"找到了"<<endl;
        }
        else
        {
            cout<<"没有找到"<<endl;
        }

    }
3.8.6set和multiset的区别
  • set不可以插入重复的值,multiset可以
  • set插入数据的同时会返回插入的结果,表示插入是否成功
  • multiset不会检测数据因此可以重复插入数据
    #include<iostream>
    #include<set>
    using namespace std;

    int main()
    {
        //不能插入重复的数
        set<int>s;
        //set容器只有insert这一种插入数据的方式
        s.insert(20);
        auto res=s.insert(30);//set的insert返回是一个系统自带的类模板下的类类型(队组) 第一个参数是容器的迭代器,第二个参数是bool类型,是否插入成功决定返回值
       pair<set<int>::iterator,bool>res2=s.insert(10);
       if(res.second)
       {
           cout<<*(res.first);
       }
       if(res2.second)
       {
           cout<<*res2.first;
       }
       //能插入重复的数
       multiset<int>ms;
       auto res3=ms.insert(10);
       multiset<int>::iterator res4=ms.insert(20);//multiset的insert返回值是一个迭代器
       cout<<*res3<<*res4;
        
    }

总结:

  • 运行重复插入数据用multiset不允许用set
3.8.7pair的使用-pair队组的创建

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-we2p7tvt-1662911759195)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220415151501704.png)]

#include<iostream>
#include<set>
#include <string>
 using namespace std;
 void test()
    {
        //第一种方式
        pair<string,int>p("你好",5);
        cout<<p.first<<p.second;
        //第二种方式
        pair<string,int>p2= make_pair("欢饮",8);
        cout<<p2.first<<p2.second;
    }
int main()
 {
        test();
 }
3.8.8set容器排序
  • set容器的默认排序是从小到大 利用仿函数可以改变排序规则

对于内置数据类型:

#include<iostream>
#include<set>
using namespace std;
class Compare//仿函数重载()符号
{
public:
    bool operator()(int v1,int v2)
    {
        return v1>v2;//降序 顺序和传进来的参数顺序有关
    }
};
void printf(set<int,Compare>&s)
{
    for(auto p=s.begin();p!=s.end();p++)
    {
        cout<<*p<<" ";//指针是迭代器的一种
    }
}
void test()
{
    set<int,Compare>s;
    s.insert(1);
    s.insert(4);
    s.insert(6);
    s.insert(8);
    printf(s);
}
int main()
{
 test();
}

对于自定义数据类型:

#include<iostream>
#include<set>
#include<string>
using namespace std;
class Person
{
public:
    int age;
    string name;
    Person(int age,string name)
    {
        this->age=age;
        this->name=name;
    }
};
class Compare//仿函数重载()符号
{
public:
    bool operator()(const Person p1,const Person p2)
    {
        return p1.age>p2.age;//降序 顺序和传进来的参数顺序有关
    }
};
void printf(set<Person,Compare>&s)
{
    for(auto p=s.begin();p!=s.end();p++)
    {
        cout<<p->name<<" "<<p->age<<endl;//指针是迭代器的一种
    }
}
void test()
{
    set<Person,Compare>s;
    Person p1(3,"小王");
    Person p2(8,"小吴");
    Person p3(1,"小陈");
    s.insert(p1);
    s.insert(p2);
    s.insert(p3);
    printf(s);
}
int main()
{
 test();
}
3.9map和multimap容器
3.9.1map的基本概念

简介:

  • map中所有元素都是pair
  • pair中的第一个元素为key(键值)起到索引的作用,第二个元素为value(实值)
  • 所有的元素都会根据元素的键值自动排序

本质:

  • 本质是由二叉树实现的

优点:

  • 可以根据key值快速找到value

map和mutinap的区别:

  • map不允许有相同的key值
  • mutimap运行容器有相同的key值
3.9.2map的构造和赋值

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bNdnayit-1662911759196)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220416092015203.png)]

#include<iostream>
#include<map>
void printf(std::map<int,int>&m)
{
    for(std::map<int,int>::iterator it=m.begin();it!=m.end();++it)
    {
        std::cout<<(*it).first<<" "<<(*it).second<<std::endl;
    }
    std::cout<<std::endl;

}
int main()
{
    std::map<int,int>m;
    m.insert(std::pair<int,int>(1,1));
    m.insert(std::pair<int,int>(2,2));
    m.insert(std::pair<int,int>(3,3));

    printf(m);

    std::map<int,int>m1(m);
    printf(m1);

    std::map<int,int>m2;
    m2=m1;
    printf(m2);

    std::cout<<sizeof(m);//存放元素的总字节数
}
3.9.3map的大小和交换

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-chWITtaa-1662911759197)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220416093555601.png)]

注意:大小返回的是队组的个数或者说是value值的个数

3.9.4map的插入和删除

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2xkURMz1-1662911759197)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220416093853943.png)]

#include<iostream>
#include<map>
using namespace  std;
void printf(std::map<int,int>&m)
{
    for(std::map<int,int>::iterator it=m.begin();it!=m.end();++it)
    {
        std::cout<<(*it).first<<" "<<(*it).second<<std::endl;
    }
    std::cout<<std::endl;

}

int main()
{
    std::map<int,int>m;
    //三种插入方式
    //第一种
    m.insert(pair<int,int>(1,1));//匿名对象
    //第二种
    m.insert(make_pair(2,2));
    //第三种
    m.insert(map<int,int>::value_type(3,3));
    printf(m);
    //删除
    m.erase(m.begin());//迭代器指定元素
    m.erase(2);//根据键值删除
    m.erase(m.cbegin(),m.cend());//指定区间删除 c表示const

    //清空
    m.clear();
}
3.9.5查找和统计

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Oar1cxnD-1662911759198)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220416102444854.png)]

注意:map容器重载了[]可以利用其键值找到对应的元素 []中填键值

3.9.6map容器的排序操作
  • map的容器默认情况下按照key值的大小从小到大进行排序 利用仿函数可以改变排序规则

类似于set容器的排序。

4.1函数对象(仿函数)

函数对象是一个广泛的概念,因为所有具有函数行为的对象都可以称为函数对象。这是一个高级抽象,我们不关心对象到底是什么,只要其具有函数行为即可。函数行为是指可以使用()调用并传递参数

4.1.1函数对象的基本概念

概念:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RkmWsmBI-1662911759198)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220419210237754.png)]

4.1.2函数对象的使用

特点:

  • 函数对象在使用的时候可以像普通函数那样调用,可以有参数,可以有返回值
  • 函数对象超出普通函数的概念,函数对象可以有自己的状态
  • 函数对象可以作为参数传递
#include<iostream>
#include <string>
using namespace std;
class Myfunc
{
public:
    Myfunc(string s):s(s),count(0){}
    void operator()(string str)
    {
        cout<<s<<" "<<str<<endl;
        count++;
    }

public:
    string s;
    int count;
};
//1.当作普通函数使用
void test01()
{
    Myfunc m("你好啊");
    m("中国");
}
//2.函数对象可以有自己的状态
void test02()
{
    Myfunc m1("你好啊");
    m1("中国");
    m1("中国");
    m1("中国");
    m1("中国");
    cout<<"被调用的次数为"<<m1.count<<endl;
}
//3.函数对象可以作为参数传递
void dowork(Myfunc &m,string test)
{
    m(test);
}
void test03()
{
    Myfunc m3("你好啊");
    dowork(m3,"中国");
}
int main()
{
    test01();
    test02();
    test03();
}

4.2谓词
4.2.1一元谓词

概念:

  • 返回bool类型的仿函数称为谓词
  • 如果operator()接受一个参数为一元谓词
  • 如果operator()接受两个参数为二元谓词
#include<iostream>
#include<algorithm>
#include<vector>
using namespace  std;
class Mycmp
{
public:
    bool operator()(int val)
    {
        return val>5;
    }
};
int main()
{
vector<int>v;
for(int i=0;i<7;i++)
{
    v.push_back(i);
}
//找出元素大于5的数

auto x=find_if(v.begin(),v.end(),Mycmp());//传参是传对象 所以这里传一个匿名对象
if(x==v.end())
    cout<<"没有找到"<<endl;
else
    cout<<"找到了是"<<*x<<endl;
}
4.2.2二元谓词
#include<iostream>
#include<algorithm>
#include<vector>
using namespace  std;
class Mycmp
{
public:
    bool operator()(int v1,int v2)
    {
        return v1>v2;
    }
};
int main()
{
vector<int>v;
v.push_back(10);
v.push_back(12);
v.push_back(12);
v.push_back(11);
v.push_back(15);
sort(v.begin(),v.end(),Mycmp());//匿名对象
for(int i=0;i<5;++i)
{
    cout<<v[i]<<" ";
}
}
4.3内建函数对象
4.3.1内建函数对象的意义

概念:STL内建了一些函数对象

分类:

  • 算术仿函数
  • 关系仿函数
  • 逻辑仿函数

用法:

  • 这些仿函数所产生的对象,用法和一般函数完全相同
  • 使用内建函数对象,需要引入头文件 #include
4.3.2算术仿函数

功能描述:

  • 实现四则运算
  • 其中negate是一元运算,其他都是二元运算

仿函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Eq6Zbtz9-1662911759199)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220420162000605.png)]

#include<iostream>
using namespace std;
#include<functional>
void test()
{
    negate<int>n;//取反
    cout<<n(10)<<endl;
    plus<int>m;//加法
    m(10,20);
    cout<<m(10,20)<<endl;
}
int main()
{
    test();
    return 0;
}
4.3.3关系仿函数

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-piw0dQFz-1662911759199)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220420164333200.png)]

#include <iostream>
#include<algorithm>
#include<vector>
#include <functional>
using namespace std;

int main()
{
    vector<int>v;
    v.push_back(20);
    v.push_back(90);
    v.push_back(30);
    v.push_back(40);
    v.push_back(60);
    //Stl自建仿函数 大于仿函数
    sort(v.begin(),v.end(), greater<int>());//创建了一个匿名对象
    for(auto x=v.begin();x!=v.end();x++)
    {
        cout<<*x<<" ";
    }
	return 0;
}

4.3.4逻辑仿函数

函数原型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2ecv4iCx-1662911759200)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220425201122498.png)]

#include <iostream>
#include<algorithm>
#include<vector>
#include <functional>
using namespace std;

int main()
{
    vector<bool>v;
    v.push_back(true);
    v.push_back(false);
    v.push_back(true);
    v.push_back(false);
    v.push_back(true);
    for(auto x=v.begin();x!=v.end();x++)
    {
        cout<<*x<<" ";
    }
    cout<<endl;
    //将容器取非装入另一个容器
    vector<bool>v2;
    v2.resize(v.size());
    transform(v.begin(),v.end(),v2.begin(),logical_not<bool>());//最后一个参数是仿函数,创建一个匿名对象
    //transform 是一个搬运函数
    for(auto x=v2.begin();x!=v2.end();x++)
    {
        cout<<*x<<" ";
    }
    //将容
	return 0;
}

5.STL中常用的算法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JIaCnxty-1662911759200)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220427184532505.png)]

5.1常用遍历算法
5.1.1for_each算法
5.1.2transform算法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4aCnGLaK-1662911759201)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220427190646281.png)]

#include<iostream>
#include<algorithm>
#include<vector>
class Mytarget
{
public:
    int operator()(int a)
    {
        return a;
    }
};
class Myout
{
public:
    void operator()(int val)
    {
        std::cout<<val<<" ";
    }
};
using namespace std;
int main()
{
    vector<int>v;
    v.push_back(10);
    v.push_back(9);
    v.push_back(8);
    v.push_back(7);
    vector<int>tagetv(5);
    transform(v.begin(),v.end(),tagetv.begin(),Mytarget());//遍历容器且搬运数据 从一个容器到另一个容器
    for_each(tagetv.begin(),tagetv.end(),Myout());
}
5.2常用的查找算法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RZFN4Ftt-1662911759201)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220427191537478.png)]

5.2.1find

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ej2MrU4x-1662911759201)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220427191828711.png)]

#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;
//内置数据类型

void test01()
{
    vector<int>v;
    v.push_back(10);
    v.push_back(9);
    v.push_back(8);
    v.push_back(7);

    auto pos=find(v.begin(),v.end(),5);
    if(pos!=v.end())
    {
        cout<<"找到了"<<endl;
    }
    else
    {
        cout<<"没有找到"<<endl;
    }
}
//自定义数据类型
class Person
{
public:
    Person(string name,int age)
    {
        this->age=age;
        this->name=name;
    }
    bool operator==(const Person& p)//根据find的底层重载==号
    {
        if(this->name==p.name&& this->age==p.age)
        {
            return true;
        }
        else
        {
            return false;
        }

    }
    int age;
    string name;
};
void test02()
{
    Person p("a",18);
    Person p1("b",19);
    Person p2("c",17);
    Person p3("d",16);
    vector<Person>v;
    v.push_back(p1);
    v.push_back(p2);
    v.push_back(p3);
    v.push_back(p);

    Person p4("b",19);
    auto x=find(v.begin(),v.end(),p4);
    if(x!=v.end())
    {
        cout<<"找到了"<<endl;
    }
    else
    {
        cout<<"没有找到"<<endl;
    }
}

int main()
{
    test01();
    test02();
}
5.2.2find_if(按条件查找)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rxfIzlVI-1662911759202)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220427194721590.png)]

#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;
class Person
{
public:
    Person(string name,int age)
    {
        this->age=age;
        this->name=name;
    }

    int age;
    string name;
};
//内置类型
class Mycmp
{
public:
    bool operator()(int val)
    {
        return val>5;//一元谓词
    }
    bool operator()(const Person&p)
    {
        return p.age>20;//一元谓词
    }
};
void test01()
{
    vector<int>v;
    v.push_back(10);
    v.push_back(9);
    v.push_back(8);
    v.push_back(7);

    auto pos=find_if(v.begin(),v.end(),Mycmp());//满足条件则成立
    if(pos!=v.end())
    {
        cout<<"找到了"<<endl;
    }
    else
    {
        cout<<"没有找到"<<endl;
    }
}
//自定义数据类型
//class Person
//{
//public:
//    Person(string name,int age)
//    {
//        this->age=age;
//        this->name=name;
//    }
//
//    int age;
//    string name;
//};
void test02()
{
    Person p("a",18);
    Person p1("b",19);
    Person p2("c",17);
    Person p3("d",16);
    vector<Person>v;
    v.push_back(p1);
    v.push_back(p2);
    v.push_back(p3);
    v.push_back(p);

    Person p4("b",19);
    auto x=find_if(v.begin(),v.end(),Mycmp());
    if(x!=v.end())
    {
        cout<<"找到了"<<endl;
    }
    else
    {
        cout<<"没有找到"<<endl;
    }
}

int main()
{
    test01();
    test02();
}
5.2.3adjacent_find

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ItqVYFrh-1662911759202)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220427201934402.png)]

5.2.4binary_search(二分查找)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KOS8MXAb-1662911759203)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220427202405342.png)]

find和binary_search的区别

  • 返回值不一样 find返回的是迭代器,binary_search返回的是bool类型
  • find有序无序均可以查找 binary_search只能用于有序序列中
  • binary_search查找速度很高
5.2.5count

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cfh0dSAw-1662911759203)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220427202919243.png)]

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

void test01()
{
    vector<int>v;
    v.push_back(10);
    v.push_back(10);
    v.push_back(10);
    v.push_back(10);
    cout<<"10的个数为:"<<count(v.begin(),v.end(),10);
}

int main()
{

    test01();

}
5.2.6count_if(按条件查找)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nsZJPsk5-1662911759204)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220427205227054.png)]

5.3常用的排序算法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3YA833n4-1662911759204)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220427205407718.png)]

5.3.1sort排序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SYcvLVgD-1662911759204)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220427205440717.png)]

注意:第三个参数可填可以不填 如果填的话填函数名或者谓词都行

5.3.2random_shuffle

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tj5ScXey-1662911759205)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220427205605061.png)]

#include<iostream>
#include<algorithm>
#include<vector>
#include <ctime>
using namespace std;
void Myrrint(int val)
{
    cout<<val<<" ";
}
void test01()
{
    //随机数的种子
    srand(static_cast<unsigned >(time(NULL)));//根据时间的变化是每一次打乱的顺序不一样
    vector<int>v;
    v.push_back(10);
    v.push_back(50);
    v.push_back(30);
    v.push_back(2);
    random_shuffle(v.begin(),v.end());
    for_each(v.begin(),v.end(), Myrrint);
}

int main()
{
    test01();
}
5.3.3merge

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UoMYLqmr-1662911759205)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220427213935538.png)]

注意:必须是有序的!!!

5.3.4reverse

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RE6h4dyx-1662911759206)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220427214147339.png)]

注意:跟vector容器的resrrver预留空间成员函数要区分开来

5.4常用的拷贝和替换算法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nxeXBjUc-1662911759206)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220427214356276.png)]

5.4.1copy

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-24VsvnVf-1662911759206)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220427214428510.png)]

注意;目标容器要提前开辟空间

5.4.2replace

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eAt48YFu-1662911759207)(C:\Users\28108\AppData\Roaming\Typora\typora-user-images\image-20220427214713451.png)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值