当前位置: 首页 > news >正文

【C++】vector 模拟实现

vector

  • vector 容器
  • vector 基本使用
    • vector 定义
    • 库中各类接口的使用
      • 迭代器
      • 容量相关接口
      • 元素访问相关接口
      • 元素修改相关接口
  • 模拟实现 vector
    • 前期准备
    • 构造与析构
    • 赋值运算符重载
    • 迭代器相关
    • 容量相关
    • 元素访问相关
    • 元素的修改相关
    • 二维数组的创建
    • 对于自定义类型数据的测试

vector 容器

C++ STL 中的 vector 就类似于 C 语言当中的数组,但是 vector 又拥有很多数组没有的接口,使用起来会更加的方便。
相比于 STL 中的 string ,vector 可以定义不同的数据类型

vector 基本使用

vector 定义

template < class T, class Alloc = allocator > class vector;

方式一:创建 vector 对象,不进行初始化

vector (const allocator_type& alloc = allocator_type());

方式二:创建 vector 对象,容量为 n,并赋值为 val

vector (size_type n, const value_type& val = value_type(),
const allocator_type& alloc = allocator_type());

方式三:创建 vector 对象,并采用区间赋值

vector (InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type());

方式四:拷贝构造

vector (const vector& x);

代码演示:

    vector<int> v;   //定义一个 int 类型变量vector<int> v0{ 1,2,3,4,5,6,7,8,9 };   //定义 int 数组并进行列表赋值PrintVector(v0);vector<int> v1(10, 5);   //定义一个 int 类型数组,数组内容为 10 个 5PrintVector(v1);int arr[] = { 1,2,3,4,5,6 };      //区间构造vector<int> v2(arr, arr + sizeof(arr) / sizeof(arr[0]));PrintVector(v2);string s("hello");     //采用迭代器构造vector<char> v3(s.begin(), s.end());PrintVector(v3);vector<char> v4(v3);   //拷贝构造PrintVector(v4);

定义一个打印函数可以很明显的观察到定义结果:

template<class T>
void PrintVector(const vector<T>& v)
{for (auto e : v)cout << e << " ";cout << endl;
}

在这里插入图片描述

库中各类接口的使用

迭代器

在这里插入图片描述

迭代器的本质是指针,其指针指向如下图:

在这里插入图片描述
begin() 指向空间起始位置,end() 指向最后一个有效元素的下一个位置

在这里插入图片描述

rbegin() 指向最后一个有效元素的下一个位置,rend() 指向空间的起始位置。

代码演示:

在这里插入图片描述

容量相关接口

在这里插入图片描述

代码演示:

(1)测试 size() 、capacity()、以及 resize()

vector<int> v{ 1,2,3,4,5,6 };PrintVector(v);cout << "v.size() = " << v.size() << endl;cout << "v.capacity() = " << v.capacity() << endl;cout << "----------------------------------------------------" << endl;//resize 修改有效元素个数v.resize(10, 0);   //将有效元素个数修改为 10,多余空间用 0 来进行填充PrintVector(v);cout << "v.size() = " << v.size() << endl;cout << "v.capacity() = " << v.capacity() << endl;cout << "----------------------------------------------------" << endl;v.resize(20);cout << "v.size() = " << v.size() << endl;cout << "v.capacity() = " << v.capacity() << endl;cout << "----------------------------------------------------" << endl;v.resize(4);        //有效元素个数缩小为 4PrintVector(v);cout << "v.size() = " << v.size() << endl;cout << "v.capacity() = " << v.capacity() << endl;cout << "----------------------------------------------------" << endl;

在这里插入图片描述
可以发现:
resize 修改有效元素个数时,size 会进行相应的扩大或缩小变化,capacity 不一定会变化(有效元素增多时,若容量足够则capacity不变,否则会扩容;有效元素减少时,capacity 不变)

(2)测试 reserve

vector<int> v{ 1,2,3,4,5,6 };PrintVector(v);cout << "v.size() = " << v.size() << endl;cout << "v.capacity() = " << v.capacity() << endl;cout << "----------------------------------------------------" << endl;//reserve 修改容量v.reserve(10);PrintVector(v);cout << "v.size() = " << v.size() << endl;cout << "v.capacity() = " << v.capacity() << endl;cout << "----------------------------------------------------" << endl;v.reserve(30);PrintVector(v);cout << "v.size() = " << v.size() << endl;cout << "v.capacity() = " << v.capacity() << endl;cout << "----------------------------------------------------" << endl;v.reserve(10);PrintVector(v);cout << "v.size() = " << v.size() << endl;cout << "v.capacity() = " << v.capacity() << endl;cout << "----------------------------------------------------" << endl;

在这里插入图片描述

可以发现:
reserve 修改容量时,size 是不会发生变化的(因为有效元素个数不变),若空间容量扩大则 capacity 会相应的进行扩大,若空间容量缩小时 capacity 是不会发生变化的

(3)测试 empty

empty 是进行判空的接口

在这里插入图片描述

元素访问相关接口

在这里插入图片描述

(1)下标运算符访问 operator[]

在这里插入图片描述

越界测试:越界触发 assert 异常

在这里插入图片描述

(2)at 访问

在这里插入图片描述

越界测试:越界抛出 out_of_range 异常

在这里插入图片描述
(3)获取首尾元素 front back

在这里插入图片描述

元素修改相关接口

在这里插入图片描述

(1)尾插 push_back

在这里插入图片描述

(2)尾删 pop_back

在这里插入图片描述

(3)任意位置插入 insert

vector<int> v{ 1,2,3 };cout << "v.size() = " << v.size() << endl;cout << "v.capacity() = " << v.capacity() << endl;cout << "-----------------------------------------" << endl;v.insert(v.begin(), 100);  //在起始位置插入 100PrintVector(v);cout << "v.size() = " << v.size() << endl;cout << "v.capacity() = " << v.capacity() << endl;cout << "-----------------------------------------" << endl;int arr[] = { 0,200,300,400 };v.insert(v.begin(), arr, arr + sizeof(arr) / sizeof(arr[0]));    //起始位置插入arr数组中元素PrintVector(v);cout << "v.size() = " << v.size() << endl;cout << "v.capacity() = " << v.capacity() << endl;cout << "-----------------------------------------" << endl;v.insert(v.end(), 9);   //尾部插入元素 9----------------同理也可以插入数组 arrPrintVector(v);cout << "v.size() = " << v.size() << endl;cout << "v.capacity() = " << v.capacity() << endl;cout << "-----------------------------------------" << endl;v.insert(v.end(), arr, arr + sizeof(arr) / sizeof(arr[0]));    //尾部插入arr数组中元素PrintVector(v);cout << "v.size() = " << v.size() << endl;cout << "v.capacity() = " << v.capacity() << endl;cout << "-----------------------------------------" << endl;

在这里插入图片描述

(4)任意位置删除 erase

在这里插入图片描述

(5)清空 clear

在这里插入图片描述

模拟实现 vector

前期准备

迭代器的本质就是指针,模拟实现 vector 容器,我们需要定义三个指针 :指向起始位置 start,指向最后一个有效元素的下一个位置 finish ,指向容器最后一个位置 endofstorage:

namespace xx {  //自定义命名空间template<class T>     //定义模板类型class vector{public:typedef T* iterator;   //迭代器  等价于  T 类型指针private:iterator start;   //空间起始位置iterator finish;  //最后一个有效元素的下一个位置iterator endofstorage;  //最后一个容量空间位置};
}

在这里插入图片描述

构造与析构

构造函数

(1)默认无参构造

vector() :start(nullptr), finish(nullptr), endofstorage(nullptr){}

(2)构造具有 n 个对象值为 val 的容器 (数据类型为模板类型 T)

vector(int n, const T& val = T()){start = new T[n];     //创建新空间for (size_t i = 0; i < n; ++i) {start[i] = val;     //对空间进行赋值操作}finish = start + n;      //修改 finish 指向---最后一个有效元素的下一个位置endofstorage = finish;   //修改容量指针}

注意:
第二个参数 val 是一个缺省参数,对于内置类型,T() 的值为 0;对于自定义类型, T() 调用的是该自定义类型的默认构造函数
因此,对于自定义类型一定要有默认的构造函数,否则会报错

(3)使用迭代器进行构造

		template<class Iterator>vector(Iterator first, Iterator last)  //区间构造{auto it = first;size_t n = 0;while (it != last) {++it;n++;  //统计区间中元素个数}start = new T[n];   //开辟空间finish = start;while (first != last) {    //进行赋值*finish = *first;++first; ++finish;}endofstorage = finish;    //修改容量指针}

(4)拷贝构造

vector(const vector<T>& v){size_t n = v.size();     //记录 v 中元素个数start = new T[n];     //创建新空间for (size_t i = 0; i < n; ++i){start[i] = v[i];      //进行赋值操作}finish = start + n;    //修改指向endofstorage = finish;}

新写法(参考上一篇博客深浅拷贝问题)

vector(const vector<T>& v){vector<T> tmp(v.begin(),v.end());   //定义临时对象--调用迭代器构造方法this->swap(tmp);    //进行资源交换}

析构函数

~vector(){if (start) {delete[] start;start = finish = endofstorage = nullptr;}}

测试代码

void MyvectorTest0()
{xx::vector<int> v1;xx::vector<int> v2(10, 5);   int arr[] = { 1,2,3,4,5 };  //区间构造xx::vector<int> v3(arr, arr + sizeof(arr) / sizeof(arr[0]));xx::vector<int> v4(v2);  //拷贝构造//遍历一:for (int i = 0; i < v2.size(); ++i) {cout << v2[i] << " ";}cout << endl;//遍历二:for (auto e : v3)cout << e << " ";cout << endl;//遍历三:auto it = v4.begin();while (it != v4.end()) {cout << *it << " ";++it;}cout << endl;}

会发现在运行代码时候出现的问题:
在这里插入图片描述

分析:

在构造 v2 时候,会调用区间构造方法,进行参数类型的推演,由于构造 v2 的两个参数都是 int 类型,故编译器会根据类型推演的结果来选择合适的构造方法,又因为构造 n 个值为 val 的构造方法中参数类型为 size_t , int,所以编译器认为类型不匹配,排除该构造方法,选用了迭代器区间的构造方法(参数类型实例化之后都为 int 类型),因此,为了实现构造 n 个值为 val 的空间构造,我们需要对构造函数进行一定的修改,使得其调用更准确:

在这里插入图片描述

赋值运算符重载

vector<T>& operator=(vector<T> v) {  //因为参数是传值类型,故在传参过程中会进行一次拷贝构造的调用//赋值运算符重载this->swap(v);    //直接进行交换(可以参考上一篇博客中深浅拷贝内容)return *this;}

迭代器相关

//迭代器iterator begin(){return start;}iterator end(){return finish;}

容量相关

(1)size、capacity、empty 的实现

		size_t size()const {return finish - start;}size_t capacity()const {return endofstorage - start;}bool empty()const {return finish == start;}

(2)resize :修改有效元素个数

void resize(size_t newsize, const T&val = T()){size_t oldsize = size();if (newsize <= oldsize) { //缩小有效元素finish = start + newsize;    //容量不变}else {//有效元素增大//需要扩容size_t cap = capacity();if(newsize > cap)reserve(newsize);for (size_t i = oldsize; i < newsize; ++i) {//多出来的空间填充start[i] = val;}finish = start + newsize;//endofstorage = finish;}}

(3)reserve:修改容量

void reserve(size_t newcapacity){size_t oldcapacity = capacity();if (newcapacity > oldcapacity) {//开辟新空间T* tmp = new T[newcapacity];if (start) {拷贝元素:memcpy(内存拷贝--------将一段空间中的内容原封不动的拷贝到新空间----浅拷贝) 按字节拷贝涉及到资源管理时,memcpy 属于浅拷贝//memcpy(tmp, start, sizeof(T)*size());for (size_t i = 0; i < size(); ++i) {tmp[i] = start[i];}//释放旧空间delete[] start;}size_t sz = size();start = tmp;finish = start + sz;   //**********endofstorage = start + newcapacity;}}

代码测试:

(1)测试 resize (含 size, capacity 的测试)
在这里插入图片描述
(2)测试 reserve
在这里插入图片描述

元素访问相关

(1)获取首尾元素 front back

T& front(){return *start;}const T& front()const{return *start;}T& back(){return *(finish - 1);}const T& back()const{return *(finish - 1);}

(2)下标访问

T& operator[](size_t index){assert(index < size());     //注意区分异常处理方式return start[index];}const T& operator[](size_t index)const{assert(index < size());return start[index];}

(3)at 访问

T& at(size_t index){if (index >= size())throw out_of_range("vector at method: index out_of_range"); //抛出异常return start[index];}const T& at(size_t index)const{if (index >= size())throw out_of_range("vector at method: index out_of_range");return start[index];}

代码测试:

在这里插入图片描述

元素的修改相关

(1)尾插

void push_back(const T& val){//进行尾插,判断容量是否足够if (finish == endofstorage) {reserve(capacity() * 2 + 3);  //按照2倍进行扩容}*finish = val;++finish;}

(2)尾删

void pop_back(){//进行尾删if (empty())return;--finish;       //直接修改尾指针}

(3)任意位置插入

//insert 插入元素的时间复杂度 O(n)iterator insert(iterator pos, const T&val){//判断插入位置的合法性if (pos < begin() || pos > end())return end();//任意位置进行插入if (finish == endofstorage)reserve(capacity() * 2); //扩容auto it = finish - 1;while (it >= pos) {       //元素后移*(it + 1) = *it;--it;}*it = val;     //当前 it 指向的就是 pos 的位置++finish;return it;            //返回新插入的元素的位置}

(4)任意位置删除

删除单个元素:

iterator erase(iterator pos){//删除任意位置元素if (empty())return end();if (pos < begin() || pos >= end())return  end();//位置合理auto it = pos;while (it != end() - 1)  //end() 表示最后一个有效元素的下一个位置{*it = *(it + 1);      //元素前移--it;}--finish;          //删除元素需要修改尾指针位置return pos;}

删除区间元素:

iterator erase(iterator start, iterator last){if (empty())return end();if (start < begin() || start >= end())return end();//位置合法, 删除区间auto beg = start;auto en = last;int n = last - start;    //要删除的元素个数while (en != end()){*beg = *en;++beg; ++en;//--finish;}finish -= n;return start;   //返回删除的区间首元素位置}

(5)清空

void clear(){erase(begin(), end());}

(6)交换函数

void swap(vector<T>& v){std::swap(start, v.start);std::swap(finish, v.finish);std::swap(endofstorage, v.endofstorage);}

测试代码:

(1)测试尾插尾删:

在这里插入图片描述
(2)测试任意位置的插入删除:

在这里插入图片描述

(3)清空:

在这里插入图片描述

二维数组的创建

创建一个五行六列数组,数组中元素值都为 8:

void MyvectorTest3()
{xx::vector<xx::vector<int>>  vv(5, xx::vector<int>(6, 8));  //创建有 5 个元素的数组,数组中元素用 vector<int>(6,8) 来进行填充for (size_t i = 0; i < vv.size(); ++i){for (size_t j = 0; j < vv[i].size(); ++j)cout << vv[i][j] << " ";cout << endl;}
}

在这里插入图片描述

对于自定义类型数据的测试

上述的测试我们都是基于内置类型int数据的测试,发现代码可以正确运行没有报错,那针对于自定义类型数据是否正确呢?

(1)定义一个日期类:

class Date {
public:Date(int year = 1990, int month = 1, int day = 20){_year = year;_month = month;_day = day;}Date(const Date& d){//拷贝构造_year = d._year;_month = d._month;_day = d._day;}~Date() {}
private:int _year;int _month;int _day;
};void MyvectorTest4()
{xx::vector<Date> d;      //定义 Date 类型数组d.push_back(Date(2023, 1, 1));     //插入元素--------Date 构造函数必须为带缺省值的构造方法d.push_back(Date(2023, 1, 2));d.push_back(Date(2023, 1, 3));d.push_back(Date(2023, 1, 4));d.push_back(Date(2023, 1, 5));cout << d.size() << endl;
}

运行改代码显式可以正确运行,因为 Date 类不存在资源的处理,那针对于 string 类是否正常?
我们来试试:

(2)定义 string 类:

class String {
public:String(const char* str=""):_str(nullptr){//构造if (nullptr == str)str = "";_str = new char[strlen(str) + 1];strcpy(_str, str);}String(const String& s):_str(new char[strlen(s._str)+1]){//拷贝构造strcpy(_str, s._str);}String& operator=(const String& s){if (this != &s) {//不是给自己的赋值char* tmp = new char[strlen(s._str) + 1];strcpy(tmp, s._str);delete[] _str;_str = tmp;}return *this;}//String& operator=(const String s)//{//	if (this != &s) {//		//新写法//		this->swap(s._str);//	}//	return *this;//}~String(){if (_str) {delete[] _str;_str = nullptr;}}
private:char* _str;
};void MyvectorTest5()
{xx::vector<String> s;s.push_back("hello");s.push_back("welcom");s.push_back("come on");cout << s.size() << endl;s.push_back("hahahha");    //此时需要进行扩容发生报错----------memcpy是属于浅拷贝}

运行发现,在最后一次尾插时发生了错误,我们来看看是什么原因导致的:

因为在第四次尾插时候需要进行扩容,因此产生了错误

在这里插入图片描述

往下运行一步就会发现问题所在了:

在这里插入图片描述

发现,在进行 memcpy 拷贝时候发生了浅拷贝,即将原空间内容原封不动的拷贝到新空间,这就导致了新空间共享旧空间的地址,会造成内存泄漏

因此,在扩容时候我们需要按元素将旧空间中元素交给新空间,而不是将地址空间也赋给新空间

进行修改:

在这里插入图片描述

修改之后程序可以正常运行。

_CrtDumpMemoryLeaks(); //检测内存泄漏

该章节完整代码:

添加链接描述

本篇内容就分享到这里啦!!!

学习编程的道路很长,要注重自我实践与验证,欢迎读者评论探讨~

相关文章:

【C++】vector 模拟实现

vectorvector 容器vector 基本使用vector 定义库中各类接口的使用迭代器容量相关接口元素访问相关接口元素修改相关接口模拟实现 vector前期准备构造与析构赋值运算符重载迭代器相关容量相关元素访问相关元素的修改相关二维数组的创建对于自定义类型数据的测试vector 容器 C S…...

canvas初体验

canvas介绍 Canvas 最初由Apple于2004 年引入&#xff0c;用于Mac OS X WebKit组件&#xff0c;为仪表板小部件和Safari浏览器等应用程序提供支持。后来&#xff0c;它被Gecko内核的浏览器&#xff08;尤其是Mozilla Firefox&#xff09;&#xff0c;Opera和Chrome实现&#x…...

JavaWeb12-线程通讯(线程等待和唤醒)

目录 1.方法介绍 1.1.wait()/wait(long timeout)&#xff1a;让当前线程进入等待状态。 1.1.1.wait执行流程 1.1.2.wait结束等待的条件 1.1.3.wait() VS wait(long timeout) 1.1.4.为什么wait要放在Object中&#xff1f; --->PS&#xff1a;wait(0) 和 sleep(0) 的区…...

江苏专转本如何事半功倍的备考

专转本如何事半功倍的备考 一个人学习成绩的优劣取决于他的学习能力&#xff0c;学习能力包括三个要素&#xff1a;规范的学习行为&#xff1b;良好的学习习惯&#xff1b;有效的学习方法。有了规范的学习行为才能培养出良好的学习习惯&#xff0c;形成了良好的学习习惯就会形成…...

linux下安装mongoDB

一、下载mongoDB包 下载地址&#xff1a; https://www.mongodb.com/try/download/community 个人建议&#xff1a;如果是学习阶段&#xff0c;使用5以下版本更好些。 二、安装及配置 1、安装 # 1、解压 $ tar -zxvf mongodb-linux-x86_64-rhel70-4.4.19-rc1.tgz# 2、迁移目…...

掌握MySQL分库分表(七)广播表、绑定表实战,水平分库+分表实现及之后的查询和删除操作

文章目录什么是广播表广播表实战数据库配置表Java配置实体类配置文件测试广播表水平分库分表配置文件运行测试什么是绑定表&#xff1f;绑定表实战配置数据库配置Java实体类配置文件运行测试水平分库分表后的查询和删除操作查询操作什么是广播表 指所有的分片数据源中都存在的…...

企业为什么需要数据可视化报表

数据可视化报表是在商业环境、市场环境已经改变之后&#xff0c;发展出来为当前企业提供替代解决办法的重要方案。而且信息化、数字化时代&#xff0c;很多企业已经进行了初步的信息化建设&#xff0c;沉淀了大量业务数据&#xff0c;这些数据作为企业的资产&#xff0c;是需要…...

5个有效的华为(HUAWEI)手机数据恢复方法

5个有效的手机数据恢复方法 华为智能手机中的数据丢失比许多人认为的更为普遍。发生这种类型的丢失有多种不同的原因&#xff0c;因此数据恢复软件的重要性。您永远不知道您的智能手机何时会在这方面垮台&#xff1b;因此&#xff0c;预防总比哀叹好&#xff0c;这就是为什么众…...

【Java并发编程】线程安全(一)Synchronized原理

Synchronized底层实现 简单来说&#xff0c;Synchronized关键字的执行主体是线程对象&#xff0c;加锁是通过一个锁对象来完成的是&#xff0c;而锁对象底层关联了一个c源码的monitor的对象&#xff0c;monitor对象底层又对应了操作系统级别的互斥锁&#xff0c;同一时刻只有一…...

[apollo]vue3.x中apollo的使用

[apollo]vue3.x中apollo的使用通过客户端获取Apollo配置环境工具的安装获取Apollo配置相关代码错误提示Uncaught (in promise) Error: Apollo client with id default not found. Use provideApolloClient() if you are outside of a component setup通过开放接口获取Apollo配置…...

system()函数启用新进程占有原进程的文件描述符表的问题

我在A程序中占用了/dev/video0这个独占模式的设备文件&#xff0c;在A中用system函数启用了B程序&#xff0c;B程序的代码中并不包含对/dev/video0的访问&#xff0c;但是我发现B程序也占用了/dev/video0&#xff0c;并且我在A程序中关闭了/dev/video0后&#xff0c;A程序不再占…...

nignx(安装,正反代理,安装tomcat设置反向代理,ip透传)

1安装nginx 安装wget Yum install -y wget 下载(链接从官网找到右键获取) 以下过程root 安装gcc Yum -y install gcc c 安装pcre Yum install -y pcre pcre-devel Openssl Yum install -y openssl openssl-devel 安装zlib Yum install -y zlib zlib-devel 安装make Yum inst…...

sklearn模块常用内容解析笔记

文章目录 回归模型评价指标R2_score预备知识R2_score计算公式r2_score使用方法注意事项参考文献回归模型评价指标R2_score 回归模型的性能的评价指标主要有:RMSE(平方根误差)、MAE(平均绝对误差)、MSE(平均平方误差)、R2_score。但是当量纲不同时,RMSE、MAE、MSE难以衡量模…...

我的 System Verilog 学习记录(2)

引言 从本文开始&#xff0c;就开始系统学习 System Verilog &#xff0c;不只是语法&#xff0c;还有结合 Questa Sim 的实际编程练习、Debug。 本文简单介绍 System Verilog 语言的用途以及学习的必要性。 前文链接&#xff1a; 我的 System Verilog 学习记录&#xff08…...

【调研报告】Monorepo 和 Multirepo 的风格对比及使用示例

带有权重的Monorepo和Multirepo对比 功能/特性MonorepoMultirepoMonorepo权重值Multirepo权重值代码管理管理多个代码库更加复杂管理单个代码库更加简单37依赖管理可以简化依赖管理依赖冲突可能会更加困难73构建和部署构建和部署更加容易构建和部署可能需要更多的配置82团队协…...

Retrofit源码分析

文章目录一、简介二、源码分析2.1Retrofit的本质流程2.2源码分析2.2.1 创建Retrofit实例步骤1步骤2步骤3步骤4步骤5总结2.2.2创建网络请求接口的实例外观模式 & 代理模式1.外观模式2. 代理模式步骤3步骤4总结2.2.3执行网络请求同步请求OkHttpCall.execute()1.发送请求过程2…...

Mybatis-Plus入门系列(20) -兼容多种数据库

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 文章目录前言方案分析1. 分页2. XML自定义SQL案例演示1. 配置2. 简单分页查询3. 带方言的分页查询参考前言 在我们实际开发软件产品过程中&#xff0c;数据库的类型可能不是确定的&#xff0c;也有客户…...

JetPack板块—Android X解析

Android Jetpack简述 AndroidX 是Android团队用于在Jetpack中开发&#xff0c;测试&#xff0c;打包&#xff0c;发布和版本管理的开源项目。相比于原来的Android Support库,AndroidX 可以称得上是一次重大的升级改进。 和Support库一样&#xff0c;AndroidX与Android 操作系…...

C++学习笔记-数字

当我们使用数字时&#xff0c;通常我们使用原始数据类型&#xff0c;例如 int&#xff0c;short&#xff0c;long&#xff0c;float 和 double 等。数字数据类型&#xff0c;它们的可能值和取值范围在讨论 C 数据类型时已经解释了。 C 定义数字 我们已经在之前笔记的各种实例…...

Nginx——Nginx的基础原理

摘要 Nginx 是俄罗斯人编写的十分轻量级的 HTTP 服务器,是一个高性能的HTTP和反向代理服务器&#xff0c;同时也是一个 IMAP/POP3/SMTP 代理服务器。Nginx 是由俄罗斯人 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的&#xff0c;它已经在该站点运行超过两年半了。…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

2024年赣州旅游投资集团社会招聘笔试真

2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码&#xff0c;实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...