C++系列-STL容器之vector

news2024/12/24 0:20:40

STL概念

  • vector基本概念
    • vector与数组的区别
    • vector容器的特点
      • 动态大小
      • 连续存储
      • 自动扩容
      • 尾部操作高效
    • vector动态扩展的含义
    • vector常用的接口示意
  • vector的构造函数
  • vector赋值操作
    • =重载赋值
    • assign赋值
  • vector的容量和大小
  • vector的插入和删除
  • vector数据存取
  • vector互换容器
    • vector互换容器的使用方法
    • vector互换容器的用途
  • vector预留空间

vector基本概念

  • vector数据结构和数组非常相似,也称为单端数组。
  • vector也是一种顺序容器,在内存中连续排列。

vector与数组的区别

  • 数组是静态空间,定义好之后,长度确定。
  • vector可以动态扩展。由于其大小(size)可变,常用于数组大小不可知的情况下来替代数组。

vector容器的特点

动态大小

  • vector容器的大小可以根据需要进行动态调整。
  • 可以在运行时根据实际需求添加或删除元素,而无需在编译时确定容器的大小。
  • vector容器会自动处理内存管理。

连续存储

  • vector容器中的元素在内存中是连续存储的。
  • 可以通过下标来访问容器中的元素,并且支持快速的随机访问。

自动扩容

  • 当向vector容器中添加元素时,如果容器的当前大小不足以容纳新元素,容器会自动扩容。
  • 扩容是通过重新分配内存并将原有元素复制到新内存空间中来实现的。
  • 这种自动扩容的特性使得vector容器能够动态地适应元素的增长。

尾部操作高效

  • vector容器中的元素是连续存储的,因此在尾部进行插入和删除操作是高效的。
  • 这是因为在尾部插入或删除元素时,不需要移动其他元素,只需调整尾部指针即可。

vector动态扩展的含义

  • 并不是在在原空间后面续接新的空间,而是开辟一个更大的空间,将原数据拷贝到新空间,并删除原空间。

vector常用的接口示意

  • 迭代器v.begin():起始元素的位置, v.end(): 最后一个元素之后的位置。
  • 迭代器v.rbegin():末尾元素的位置, v.rend(): 第一个元素之前的位置。
  • front(): 第一个元素,back(): 末尾元素。
  • push_back(): 末尾添加元素,pop_back(): 末尾删除元素。
  • vector的迭代器是支持随机访问的迭代器,也就是说迭代器可以一下跳好几个。
    在这里插入图片描述

vector的构造函数

  • vector v: 采用模板类实现,默认构造函数。
  • vector(v.begin(), v.end()): 将v对象从v.begin()到 v.end()之间的元素拷贝给正在创建的对象,包头不包尾。
  • vector(n, elem): 将n个elem拷贝给正在创建的对象。
  • vector(const vector &vec): 拷贝构造函数。
#include <iostream>
#include <vector>
using namespace std;

void print_vector(vector<int> &vec)
{
	for (vector<int>::iterator it = vec.begin(); it < vec.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}
void test01()
{
	vector<int> arr1;								// 一个空数组
	arr1.push_back(11);
	arr1.push_back(22);
	cout << "---------- arr1 ----------";
	print_vector(arr1);
	
	vector<int> arr2 {1, 2, 3, 4};					// 包含1、2、3、4这4个元素
	cout << "---------- arr2 ----------";
	print_vector(arr2);

	vector<int> arr3(4);							// 开辟4个空间,值默认为0
	cout << "---------- arr3 ----------";
	print_vector(arr3);
	
	vector<int> arr4(5, 3);							// 5个值为3的数组
	cout << "---------- arr4 ----------";
	print_vector(arr4);
	
	vector<int> arr5(arr3);							// 将arr3的所有值复制进去,array5和arr3一样
	cout << "---------- arr5 ----------";
	print_vector(arr5);

	vector<int> arr6(arr2.begin(), arr2.end());		// 将arr2的值从头开始到尾复制
	cout << "---------- arr6 ----------";
	print_vector(arr6);
	
	vector<int> arr7(arr2.rbegin(), arr2.rend());	// 将arr2的值从尾到头复制
	cout << "---------- arr7 ----------";
	print_vector(arr7);
}
int main()
{
	test01();
	system("pause");
	return 0;
}

result:
---------- arr1 ----------11 22
---------- arr2 ----------1 2 3 4
---------- arr3 ----------0 0 0 0
---------- arr4 ----------3 3 3 3 3
---------- arr5 ----------0 0 0 0
---------- arr6 ----------1 2 3 4
---------- arr7 ----------4 3 2 1

vector赋值操作

=重载赋值

  • 函数原型 vector& operator=(const vector &vec), 重载等号运算符

assign赋值

  • v1.assign(beg迭代器,end迭代器), 将[beg迭代器,end迭代器) 之间的数据拷贝给被赋值的对象。
  • v1.assign(n,elem), 将n个elem的数据拷贝给被赋值的对象。
code:
#include <iostream>
#include <vector>
using namespace std;

void print_vector(vector<int>& vec)
{
	for (vector<int>::iterator it = vec.begin(); it < vec.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}
void test01()
{
	vector<int> arr1{0,1,2,3,4,5,6,7,8,9};
	cout << "---------- arr1 ----------" << endl;
	print_vector(arr1);

	vector<int> arr2;
	arr2 = arr1;			// 直接用
	cout << "---------- arr2 ----------" << endl;
	print_vector(arr2);

	arr2.pop_back();
	arr2.pop_back();
	vector<int> arr3;
	arr3.assign(5, 3);		// 函数重载,将5个3赋值给arr3
	cout << "---------- arr3 ----------" << endl;
	print_vector(arr3);

	vector<int> arr4;
	arr4.assign(arr1.begin(), arr1.end()-4);	// 函数重载,迭代器参数, 迭代器可以加减操作
	cout << "---------- arr4 ----------" << endl;
	print_vector(arr4);
}
int main()
{
	test01();
	system("pause");
	return 0;
}

result:
---------- arr1 ----------
0 1 2 3 4 5 6 7 8 9
---------- arr2 ----------
0 1 2 3 4 5 6 7 8 9
---------- arr3 ----------
3 3 3 3 3
---------- arr4 ----------
0 1 2 3 4 5

vector的容量和大小

函数原型用途
empty()判断容器是否为空
capacity()容器的容量,容量>=size
size()返回容器中元素的个数
resize(int num)重新指定容器的长度(size)为num,若容器变长,则以默认数值填充新位置,如果容器变短,则末尾超出容器长度的元素被删除
resize(int num,elem)重新指定容器的长度(size)为num,若容器变长,则以elem填充新位置,如果容器变短,则末尾超出容器长度的元素被删除
#include <iostream>
#include <vector>
using namespace std;

void print_vector(vector<int>& vec)
{
	for (vector<int>::iterator it = vec.begin(); it < vec.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}
void test01()
{
	vector<int> arr1{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
	cout << "---------- arr1 ----------" << endl;
	print_vector(arr1);
	vector<int> arr2;
	cout << "---------- arr2 ----------" << endl;
	print_vector(arr2);

	// 判断容器是否为空
	if (arr1.empty())
	{
		printf("arr1 is empty");
	}
	else
	{
		cout << "arr1.capacity: " <<  arr1.capacity() << ", arr1.size: " << arr1.size() << endl;
	}

	if (arr2.empty())
	{
		printf("arr2 is empty\n");
	}	
	
	vector<int> arr3;
	arr3.assign(arr1.begin(), arr1.end());		// assign赋值迭代器参数
	cout << "---------- arr3 ----------" << endl;
	print_vector(arr3);
	cout << "arr3.capacity: " << arr3.capacity() << ", arr3.size: " << arr3.size() << endl;
	
	arr3.resize(7);			// resize为7,size比原数组短,超出部分删除,size减小,capacity不变
	cout << "---------- arr3.resize(7) ----------" << endl;
	print_vector(arr3);
	cout << "arr3.capacity: " << arr3.capacity() << ", arr3.size: " << arr3.size() << endl;
	
	arr3.resize(9);		// resize为10,size比原数长,超出部分填充0,size增加
	cout << "---------- arr3.resize(9) ----------" << endl;
	print_vector(arr3);
	cout << "arr3.capacity: " << arr3.capacity() << ", arr3.size: " << arr3.size() << endl;

	arr3.resize(16, 666);	// resize为16,size比原数组长,超出部分填充,size增大,自动扩展capacity
	cout << "---------- arr3.resize(16, 666); ----------" << endl;
	print_vector(arr3);
	cout << "arr3.capacity: " << arr3.capacity() << ", arr3.size: " << arr3.size() << endl;
	
}
int main()
{
	test01();
	system("pause");
	return 0;
}


reult:
---------- arr1 ----------
0 1 2 3 4 5 6 7 8 9
---------- arr2 ----------

arr1.capacity: 10, arr1.size: 10
arr2 is empty
---------- arr3 ----------
0 1 2 3 4 5 6 7 8 9
arr3.capacity: 10, arr3.size: 10
---------- arr3.resize(7) ----------
0 1 2 3 4 5 6
arr3.capacity: 10, arr3.size: 7
---------- arr3.resize(9) ----------
0 1 2 3 4 5 6 0 0
arr3.capacity: 10, arr3.size: 9
---------- arr3.resize(16, 666); ----------
0 1 2 3 4 5 6 0 0 666 666 666 666 666 666 666
arr3.capacity: 16, arr3.size: 16


vector的插入和删除

函数原型用途
push_back(ele)尾部插入元素ele
insert(const_iterator pos, ele)迭代器指向位置pos插入元素ele
insert(const_iterator pos, int count, ele)迭代器指向位置pos插入count元素ele
erase(const_iterator pos)删除迭代器指向的元素
erase(const_iterator start, const_iterator end)删除迭代器从start到end之间的元素
clear()删除容器中所有元素
code:
#include <iostream>
#include <vector>
using namespace std;

void print_vector(vector<int>& vec)
{
	for (vector<int>::iterator it = vec.begin(); it < vec.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}
void test01()
{
	vector<int> v1;
	v1.push_back(11);		// 尾插
	v1.push_back(22);
	v1.push_back(33);
	cout << "---------- v1尾插 ----------" << endl;
	print_vector(v1);

	v1.pop_back();			// 尾删
	cout << "---------- v1尾删 ----------" << endl;
	print_vector(v1);

	v1.insert(v1.begin()+1, 666);	// 在迭代器指示的位置插入666
	cout << "---------- v1.insert(v1.begin()+1,666) ----------" << endl;
	print_vector(v1);

	v1.insert(v1.begin(), 5, 666);	// 在迭代器指示的位置插入5个666
	cout << "---------- v1.insert(v1.begin(), 3, 888) ----------" << endl;
	print_vector(v1);

	v1.erase(v1.begin());			// 删除迭代器指示的位置的元素
	cout << "---------- v1.erase(v1.begin()) ----------" << endl;
	print_vector(v1);

	v1.erase(v1.begin(), v1.end()-2);	// 删除迭代器指示的区域
	cout << "---------- v1.erase(v1.begin(), v1.end()-2) ----------" << endl;
	print_vector(v1);

	v1.clear();		// 清空
	cout << "---------- v1.clear() ----------" << endl;
	print_vector(v1);
}
int main()
{
	test01();
	system("pause");
	return 0;
}

result:
---------- v1尾插 ----------
11 22 33
---------- v1尾删 ----------
11 22
---------- v1.insert(v1.begin()+1,666) ----------
11 666 22
---------- v1.insert(v1.begin(), 3, 888) ----------
666 666 666 666 666 11 666 22
---------- v1.erase(v1.begin()) ----------
666 666 666 666 11 666 22
---------- v1.erase(v1.begin(), v1.end()-2) ----------
666 22
---------- v1.clear() ----------

vector数据存取

函数原型用途
at(int idx)返回索引idx所指的数据
operator[]返回索引idx所指的数据
front()返回容器中的第一个数据元素
back()返回容器中的最后一个数据元素
code:
#include <iostream>
#include <vector>
using namespace std;

void print_vector(vector<int>& vec)
{
	for (int i_loop = 0; i_loop < vec.size(); i_loop++)
	{
		cout << vec[i_loop] << " ";		// 使用[]重载访问
	}
	cout << endl;
}

void print_vector_at(vector<int>& vec)
{
	for (int i_loop = 0; i_loop < vec.size(); i_loop++)
	{
		cout << vec.at(i_loop) << " ";		// 使用v1.at(index)访问元素
	}
	cout << endl;
}

void test01()
{
	vector<int> v1{11, 22, 33, 44, 55, 66};
	print_vector(v1);
	print_vector_at(v1);
	cout << "vector容器中的第一个元素: " << v1.front() << endl;
	cout << "vector容器中的最后一个元素: " << v1.back() << endl;
	
}
int main()
{
	test01();
	system("pause");
	return 0;
}

result:
11 22 33 44 55 66
11 22 33 44 55 66
vector容器中的第一个元素: 11
vector容器中的最后一个元素: 66

vector互换容器

  • 实现两个容器内元素互换
  • v1.swap(vec), v1与vec中的元素互换

vector互换容器的使用方法

code:
#include <iostream>
#include <vector>
using namespace std;

void print_vector(vector<int>& vec)
{
	for (vector<int>::iterator it=vec.begin(); it<vec.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test01()
{
	vector<int> v1{11, 22, 33, 44, 55, 66};
	vector<int> v2{99, 88, 66, 77};
	cout << "---------- swap前 ----------" << endl;
	cout << "v1中的元素:";
	print_vector(v1);
	cout << "v1.capacity: " << v1.capacity() << ", v1.size: " << v1.size() << endl;
	cout << "v2中的元素:";
	print_vector(v2);
	cout << "v2.capacity: " << v2.capacity() << ", v2.size: " << v2.size() << endl;
	cout << "\n---------- swap后 ----------" << endl;
	
	v1.swap(v2);
	cout << "v1中的元素:";
	print_vector(v1);
	cout << "v1.capacity: " << v1.capacity() << ", v1.size: " << v1.size() << endl;
	cout << "v2中的元素:";
	print_vector(v2);
	cout << "v2.capacity: " << v2.capacity() << ", v2.size: " << v2.size() << endl;
}
int main()
{
	test01();
	system("pause");
	return 0;
}

result:
---------- swap前 ----------
v1中的元素:11 22 33 44 55 66
v1.capacity: 6, v1.size: 6
v2中的元素:99 88 66 77
v2.capacity: 4, v2.size: 4
---------- swap后 ----------
v1中的元素:99 88 66 77
v1.capacity: 4, v1.size: 4
v2中的元素:11 22 33 44 55 66
v2.capacity: 6, v2.size: 6

vector互换容器的用途

  • 可以用来收缩内存空间
    请从以下代码中一窥究竟。
code:
#include <iostream>
#include <vector>
using namespace std;

void print_vector(vector<int>& vec)
{
	for (vector<int>::iterator it = vec.begin(); it < vec.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test01()
{
	vector<int> v1;
	// 系统在开辟空间时会不断给尝试,所以capacity的值不一定是10000
	for (int i_loop = 0; i_loop < 10000; i_loop++)	
	{
		v1.push_back(i_loop);
	}
	cout << "---------- swap前 ----------" << endl;
	cout << "v1.capacity: " << v1.capacity() << ", v1.size: " << v1.size() << endl;
	
	v1.resize(3);		// 后面的数据删除,size会变小,但是capacity不会
	cout << "---------- v1.resize(3) ----------" << endl;
	print_vector(v1);
	cout << "v1.capacity: " << v1.capacity() << ", v1.size: " << v1.size() << endl;
	
	// vector<int>(v1)是创建匿名对象temp(实际没名字),会按照v1的实际size创建匿名对象,会自动将capacity缩小为size,
	// 然后temp.swap(v1),v1和temp做容器交换,将v1的capacity缩小了。
	// 当这条语句执行完之后,系统发现是匿名对象,会将其删掉,所以不会一直占用空间。
	vector<int>(v1).swap(v1);	
	cout << "\n---------- swap后 ----------" << endl;
	cout << "v1.capacity: " << v1.capacity() << ", v1.size: " << v1.size() << endl;
}
int main()
{
	test01();
	system("pause");
	return 0;
}

result:
---------- swap前 ----------
v1.capacity: 12138, v1.size: 10000
---------- v1.resize(3) ----------
0 1 2
v1.capacity: 12138, v1.size: 3

---------- swap后 ----------
v1.capacity: 3, v1.size: 3


vector预留空间

  • 减少vector在动态扩展容量时的扩展次数
    且看下面的代码:
code:
void test01()
{
	int num = 0;
	vector<int> v1;
	int* pt = NULL;
	// 系统在开辟空间时会不断给尝试,开辟一次不够,就重新开辟,每次开辟是会找一块新的区域
	for (int i_loop = 0; i_loop < 10000; i_loop++)
	{
		v1.push_back(i_loop);
		if (&v1[0] != pt)		// 判断是否是一次重新开辟的空间
		{
			pt = &v1[0];
			num++;
		}
	}
	cout << "num: " << num << endl;
}
int main()
{
	test01();
	system("pause");
	return 0;
}

result:
num: 24

从代码中可以看出,空间一共开辟了24次,当然也伴随着旧的空间释放,这些操作其实就是浪费资源。
试问怎么解决呢?且看下面代码

code:
#include <iostream>
#include <vector>
using namespace std;

void print_vector(vector<int>& vec)
{
	for (vector<int>::iterator it = vec.begin(); it < vec.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test01()
{
	int num = 0;
	vector<int> v1;
	v1.reserve(10000);		// reserve找10000大的空间,给v1预留着

	int* pt = NULL;
	// 系统在开辟空间时会不断给尝试,开辟一次不够,就重新开辟,每次开辟是会找一块新的区域
	for (int i_loop = 0; i_loop < 10000; i_loop++)
	{
		v1.push_back(i_loop);
		if (&v1[0] != pt)		// 判断是否是一次重新开辟的空间
		{
			pt = &v1[0];
			num++;
		}
	}
	cout << "num: " << num << endl;
}
int main()
{
	test01();
	system("pause");
	return 0;
}

result:
num: 1

从代码中可以看出,空间一共开辟了1次,这是因为使用v1.reserve(空间大小),系统会先预留一片空间,如果没超出,就不会开辟新的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2085715.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

音视频入门基础:WAV专题(7)——FFmpeg源码中计算WAV音频文件每个packet的size值的实现

一、引言 从文章《音视频入门基础&#xff1a;WAV专题&#xff08;6&#xff09;——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道&#xff0c;通过FFprobe命令可以显示WAV音频文件每个packet&#xff08;也称为数据包或多媒体包&#xff09;的信息&#xff0…

VMware16安装包+详细安装教程

VMware Workstation Pro16.0安装 安装包下载&#xff1a; 通过百度网盘分享的文件&#xff1a;VMware16.0.rar 链接&#xff1a;https://pan.baidu.com/s/1ZSWns5kJYUmhpZFjuKXqrQ?pwdv7s2 提取码&#xff1a;v7s2右键解压之后的安装包【VMware-workstation-full-16.0.0-16…

FrameNet介绍——从同义词语义知识库到框架语义知识库

FrameNet 是一个为期三年的项目&#xff0c;获得了 NSF&#xff08;美国国家科学基金会&#xff09;的支持&#xff0c;专注于基于语料库的计算词典编纂。 项目特点 FrameNet承诺使用语料库证据&#xff08;corpus evidence&#xff09;来进行语义和句法的概括&#xff1b; 并…

网络基础-实现在Windows系统下的socket环境地址通信

实现客户端和服务端的数据交互 1.写所要实现功能的声明&#xff08;封装在tcpsocket.h文件&#xff09; #ifndef TCPSOCKET_H #define TCPSOCKET_H//在Windows下进行网络编程&#xff0c;需要引入Windows的socket库 #include <winsock2.h> //做一些预编译工作&#xff…

MyBatis结果集复杂映射超详细版(一对多关系映射)

目录 1.一对多关系映射 1.1创建两个表&#xff1a;goods表与goods_class表 1.2xml文件中两部分&#xff1a;与(存放SQL语句)1.3数据库中&#xff1a;测试SQL语句&#xff0c;涉及到的知识点&#xff1a;左连接 1.一对多关系映射 1.1创建两个表&#xff1a;goods表与goods_c…

C++对C的扩充(8.28)

1.使用C手动封装一个顺序表&#xff0c;包括成员数组1个&#xff0c;成员变量n个 代码&#xff1a; #include <iostream>using namespace std;//类型重命名 using datatype int; #define MAX 30struct seqList { private: //私有权限datatype *data; //相当于 …

【项目源码】终于有人将打字游戏和编程英语结合起来啦!编程初学者的福音

Hello&#xff01;各位彦祖&#xff0c;亦菲们&#xff01;又是美好的一天&#xff01;今天给大家分享一个Java项目源码&#xff1a;Java打字游戏项目源码&#xff01; 看到这里&#xff0c;你可能会说&#xff01; 一个破打字游戏有什么可神气的&#xff01;&#xff01;&…

【自由能系列(中级)】状态与动作的协同机制解析 ——从马尔可夫毯到大脑功能的全方位剖析

状态与动作的协同机制解析 ——从马尔可夫毯到大脑功能的全方位剖析 Synergistic Mechanism of States and Actions —— A Comprehensive Analysis from Markov Blanket to Brain Function 核心结论&#xff1a; 中文总结&#xff1a; 系统将状态划分为内部状态和隐藏或外…

Flutter中的Key

在Flutter 中&#xff0c;Key 是 几乎所有 widget 都具有的属性。为什么 widget 具有 Key 呢&#xff1f;Key的作用是什么&#xff1f; 什么是 Key Key是Widget、Element 和 SemanticNodes 的标识符。 Key 是Widget、Element 和 SemanticNodes的唯一标识。例如对于 Widget 在 …

MyBatis的学习————下篇

目录 一、动态SQL 简介 1、if标签 2、where标签 3、trim标签 4、choose、when、otherwise 5、foreach 5.1、批量删除 5.2、批量添加 6、sql标签 二、MyBatis的缓存 1、一级缓存 2、二级缓存 3、二级缓存的相关配置 4、MyBatis缓存查询的顺序 5、 第三方缓存EHCac…

如何在Windows 11上关闭无响应的应用程序?这里有详细步骤

序言 无响应的应用程序令人沮丧,但更糟糕的是这些应用程序拒绝关闭。如果你发现自己处于这种情况,我们有几种方法可以帮助你强制关闭Windows 11 PC上的这些应用程序。让我们找出可用的解决方案。 使用键盘快捷键结束程序 关闭无响应应用程序的最简单方法是使用Windows键盘…

DataWhale AI夏令营 2024大运河杯-数据开发应用创新赛-task2

DataWhale AI夏令营 2024大运河杯-数据开发应用创新赛 YOLO(You Only Look Once)上分心得分享 YOLO(You Only Look Once) YOLO算的上是近几年最火的目标检测模型了&#xff0c;被广泛的应用在工业、学术等领域。 YOLOv1&#xff08;You Only Look Once 第一版&#xff09;于 2…

基于麒麟信安操作系统的光伏发电功率预测系统完成大规模部署建设

麒麟信安操作系统&#xff0c;作为行业数智化建设的安全根基&#xff0c;为电力业务系统提供了稳定可靠的底层平台&#xff0c;在全球能源结构转型大潮中扮演着至关重要的角色。某光伏电站项目中&#xff0c;基于麒麟信安操作系统的光伏发电功率预测系统完成大规模部署建设&…

c#如何加密exe程序防止反编译附软件

1. 先说软件&#xff0c;使用的软件是Dotfuscator&#xff0c;下载地址如下&#xff1a; 链接&#xff1a;https://pan.quark.cn/s/6f2e785c003f2. 软件使用方法&#xff0c;打开软件&#xff0c;选择Create New Project 3. 找到input&#xff0c;把你需要加密的文件导入 4.…

k8s项目的发布

目录 三种发布方式 1.蓝绿发布 2.金丝雀发布&#xff08;灰度发布&#xff09; 实验&#xff1a;k8s实现金丝雀发布 3.滚动发布&#xff08;默认形式&#xff09; 因为应用升级以及新旧业务切换&#xff0c;所以在这个过程当中如何保证对外的服务正常是一个非常重要的问题…

手把手教你如何使用Python连接MySQL数据

数据库编程是在应用程序中与数据库交互和管理数据的关键部分。MySQL是一种流行的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;在Python中进行MySQL数据库编程相对容易。 本文介绍如何使用Python进行MySQL数据库编程&#xff0c;包括连接数据库、执行SQL查询…

高频面试题:SpringMVC的执行流程

SpringMVC一直以来都是面试中的重点&#xff0c;尽管随着近年来springboot和微服务的广泛流行&#xff0c;关于对springMVC的考察比重略有下降&#xff0c;但依然是面试中的重点&#xff0c;也需要我们对其有一个比较清楚和全面的认识。 如果将java的发展史中重要的组件进行排…

备忘录模式 详解

备忘录模式 简介: 保存一个对象的某个状态&#xff0c;以便在适当的时候恢复对象, 允许在不破坏封装性的前提下&#xff0c;捕获和恢复对象的内部状态。 场景: 很多地方都用到了备忘录模式, 比如网络消息的序列化和反序列化, 数据的本地保存与加载等, 最简单的json的dump和loa…

全能与专精:探索AI模型的未来之路

AI模型&#xff1a;追求全能还是专精&#xff1f; 近日&#xff0c;OpenAI预计在秋季推出代号为“草莓”的新AI。从专注于数学问题到处理主观营销策略&#xff0c;"草莓"模型展现出惊人的多样性。而这种全能型 AI 是否代表了未来趋势&#xff1f;相比专攻于某一领域…

OpenAI 将于今年秋天推出新的先进“Strawberry草莓”生成式人工智能产品

今年秋季&#xff0c;OpenAI将推出一款备受瞩目的新型生成式人工智能产品——“草莓”。据悉&#xff0c;这款名为“草莓”的AI程序将带来一系列创新突破&#xff0c;它将大幅提升人工智能处理复杂数学题、执行战略任务以及深入探索各种主题的能力&#xff0c;而这一切无需依赖…