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

【C++】vector 的模拟实现

📢博客主页:https://blog.csdn.net/2301_779549673
📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
📢本文由 JohnKi 原创,首发于 CSDN🙉
📢未来很长,值得我们全力奔赴更美好的生活✨

在这里插入图片描述

在这里插入图片描述

文章目录

  • 📢前言
  • 🏳️‍🌈一、vector 模拟实现的基础
  • 🏳️‍🌈二、构造函数与析构函数
  • 🏳️‍🌈三、元素访问与操作函数
  • 🏳️‍🌈四、数据修改函数
  • 🏳️‍🌈五、赋值运算符重载
  • 🏳️‍🌈整体代码
  • 👥总结


📢前言

在 C++ 的编程世界中,vector 是一种极为常用的数据结构。理解其内部工作原理并进行模拟实现,能让我们更深入地掌握 C++ 编程的精髓。本文将带您走进 vector 模拟实现的世界,揭示其背后的神秘面纱,助您提升编程技能。


🏳️‍🌈一、vector 模拟实现的基础

迭代器的理解
vector 的模拟实现中,迭代器起着关键作用。vector 的迭代器本质上是一个原生指针,这使得对元素的访问和操作相对简单。通过指针的移动和解引用,能够方便地实现对 vector 中元素的遍历、读取和修改。但需要注意的是,对于不同的容器,迭代器的实现方式可能会有所不同。比如在链表等非连续存储的容器中,迭代器的实现就会更加复杂,需要考虑节点的连接和遍历逻辑。

私有成员变量的定义及作用
vector 的模拟实现中,定义了三个私有成员变量:startfinishend_of_storagestart 指针指向 vector 的第一个元素,finish 指针指向最后一个有效元素的下一个位置,end_of_storage 指针指向整个存储空间的末尾。

这三个指针共同协作,管理着 vector 的存储空间和元素范围。通过对它们的操作和维护,实现了 vector 的动态增长、元素插入、删除、容量调整等功能。例如,在扩容操作中,需要根据 end_of_storage 和 finish 的关系来判断是否需要重新分配更大的空间,并更新这三个指针的值以保证 vector 的正常运作。

	private:iterator _start = nullptr;iterator _finish = nullptr;iterator _end_of_storage = nullptr;

vector的定义

在这里插入图片描述
在这里插入图片描述

🏳️‍🌈二、构造函数与析构函数

无参构造函数
无参构造函数将三个私有成员变量 startfinishend_of_storage 初始化为 nullptr,实现如下:

vector() {_start = nullptr;_finish = nullptr;_end_of_storage = nullptr;
}

带参数的构造函数(包括 size_t 和 int 类型)
对于带参数的构造函数,当参数类型为 size_t 时,会先为 vector 分配指定数量的空间,并为每个元素进行初始化。代码如下:

vector(size_t n, const T& val = T()) {_start = new T[n];_finish = _start;_end_of_storage = _start + n;for (size_t i = 0; i < n; ++i) {*_finish++ = val;}
}

区间构造函数
区间构造函数接收两个迭代器 firstlast,通过循环将区间内的元素插入到 vector 中。代码如下:

template <class InputIterator>
vector(InputIterator first, InputIterator last) {while (first!= last) {push_back(*first);++first;}
}

拷贝构造函数
拷贝构造函数用于创建一个新的 vector 对象,其内容与原对象相同。传统写法如下:

vector(const vector<T>& v) {_start = new T[v.size()];for (size_t i = 0; i < v.size(); ++i) {_start[i] = v._start[i];}_finish = _start + v.size();_end_of_storage = _start + v.capacity();
}

析构函数
析构函数用于释放 vector 所占用的资源,当 _start 不为空时,释放动态分配的内存,并将三个指针置为 nullptr。代码如下:

~vector() {if (_start) {delete[] _start;_start = _finish = _end_of_storage = nullptr;}
}

🏳️‍🌈三、元素访问与操作函数

获取迭代器的函数
begin 函数返回一个指向 vector 起始位置的迭代器,代码实现为 iterator begin() { return _start; }
end 函数返回一个指向 vector 结束位置(即最后一个元素的下一个位置)的迭代器,实现方式为iterator end() { return _finish; }
cbegin 函数返回一个常量迭代器,指向 vector 的起始位置,代码为 const_iterator cbegin() const { return _start; }
cend 函数返回一个常量迭代器,指向 vector 的结束位置,即 onst_iterator cend() const { return _finish; }

元素访问函数
operator[] 函数用于访问 vector 中的元素。

//它实现了两种版本,一种是 const 版本,用于只读访问,代码为
const T& operator[](size_t pos) const 
{ assert(pos < size()); return _start[pos]; 
}//另一种是非 const 版本,允许通过索引修改元素的值,实现为 
T& operator[](size_t pos) 
{ assert(pos < size()); return _start[pos];
} 

获取容量和大小的函数
size 函数用于获取 vector 中元素的个数,通过计算 _finish - _start 得出,
capacity 函数用于获取 vector 的容量大小,即通过计算 _end_of_storage - _start 得到,
empty 函数用于判断 vector 是否为空,通过比较 _start_finish 是否相等来确定,

size_t size() const
{return _finish - _start;
}size_t capacity() const
{return _end_of_storage - _start;
}bool empty()
{return (_finish == _start);
}

size_t size() const 中,const 的作用主要有以下几点:

  1. 表明该函数不会修改类的成员变量:这意味着在函数内部,不能对类的非静态成员变量进行修改操作,保证了函数的只读性质。这对于保证类的封装性和数据的一致性非常重要。
  2. 允许常量对象调用该函数:如果一个对象被定义为常量,即 const 类型,那么它只能调用 const 成员函数。如果 size 函数没有 const 修饰,那么常量对象就无法调用这个函数来获取元素数量。

例如,假设有一个常量的 vector 对象 const vector v; ,如果 size 函数不是 const 的,就会导致编译错误,而有了 const 修饰,就可以正常通过 v.size() 来获取元素数量。

  1. 增强代码的可读性和可维护性:当看到一个函数被标记为 const 时,开发者可以立即知道这个函数不会修改对象的状态,有助于更好地理解代码的行为。

🏳️‍🌈四、数据修改函数

扩容函数(reserve)
reserve函数用于预分配vector的存储空间。
需要注意的是,reserve分配的内存未进行初始化,且访问未初始化的内存可能导致程序崩溃。
总之,在使用这些数据修改函数时,要特别注意迭代器失效的问题,及时更新迭代器以保证程序的正确性。

		void reserve(size_t n){if (n > capacity()){size_t old_size = size();T* tmp = new T[n];//memcpy(tmp, _start, size() * sizeof(T));// T不一定是内置类型,可能会造成乱码,得深拷贝for (size_t i = 0; i < old_size; i++){tmp[i] = _start[i];}delete[] _start;_start = tmp;_finish = _start + old_size;_end_of_storage = _start + n;}}

尾插函数(push_back)
push_back函数用于在vector的末尾添加元素。
当vector的剩余空间不足时,可能会进行内存的重新分配和数据的拷贝。
在一些情况下,这可能导致之前获取的迭代器失效。

		void push_back(const T& x){if (_finish == _end_of_storage){reserve(capacity() == 0 ? 4 : capacity() * 2);}*_finish = x;++_finish;}

改变数组长度函数(resize)
resize函数用于改变vector的有效长度。
如果resize后的长度小于当前长度,会删除多余的元素。
如果大于当前长度,会插入新的元素并进行初始化。
使用resize时,同样要关注迭代器的有效性。

		void resize(size_t n, T val = T()){if (n < size()){_finish = _start + n;}else{reserve(n);while (_finish < _start + n){*_finish = val;++_finish;}}}

插入函数(insert)
insert函数用于在vector的指定位置插入元素。它有多种用法:

  • 可以在指定位置插入单个元素,返回指向插入元素的迭代器。
  • 能在指定位置插入指定数量的相同元素。
  • 还可以插入一个区间内的元素。
    在使用insert时需要注意迭代器失效的问题。当插入元素导致vector重新分配内存时,之前获取的迭代器可能会失效。解决方法是在插入操作后重新获取迭代器。
		iterator insert(iterator pos, const T& x){assert(pos >= _start);assert(pos <= _finish);if (_finish == _end_of_storage){size_t len = pos - begin();// 防止扩容后导致相对位置发生变化reserve(capacity() == 0 ? 4 : capacity() * 2);pos = begin() + len;}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;--end;}*pos = x;++_finish;return pos;}

删除函数(erase、pop_back)
erase函数可以通过迭代器删除指定元素或指定位置的元素。
使用时要注意迭代器的正确操作,避免出现野指针导致程序错误。

pop_back函数用于删除vector的最后一个元素。
当进行删除操作时,如果导致vector内存重新分配,相关迭代器也可能失效。

		void erase(iterator pos){assert(pos >= _start);assert(pos <= _finish);iterator it = pos + 1;while (it != end()){*(it - 1) = *it;it++;}--_finish;}void pop_back() {assert(!empty());--_finish;}

🏳️‍🌈五、赋值运算符重载

在 vector 的模拟实现中,赋值运算符重载 operator= 起着重要的作用。其实现方式通常是通过复制源 vector 的元素来更新目标 vector 的内容。
常见的实现方式是创建一个临时的 vector 对象,将源 vector 的元素复制到这个临时对象中,然后通过交换操作来更新目标 vector 的状态。这样可以避免直接操作目标 vector 可能导致的内存管理问题。
赋值运算符重载的作用主要有以下几点:

  1. 方便对象之间的赋值操作,使得 vector 对象可以像基本数据类型一样进行赋值,提高了代码的简洁性和可读性。
  2. 支持不同 vector 对象之间的数据传递和更新,使得代码逻辑更加清晰和易于理解。
  3. 确保在赋值过程中正确处理内存管理,避免内存泄漏和数据错误。
		vector<T>& operator=(const vector<T>& v){if (this != &v){clear();reverse(v.size());for (auto& e : v){push_back(e);}}return *this;}

🏳️‍🌈整体代码

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<assert.h>
#include<list>
using namespace std;// 模板的原理是将我们要做的事交给编译器去// vector<vector<int>> vv(10, v);   // 有点像二维数组// vector<int> v(5, 1);namespace bit
{template<class T>class vector{public:typedef T* iterator;typedef const T* const_iterator;// C++11 前置生成默认构造vector() = default;// 拷贝构造//vector(const vector<T>& v)vector(const vector& v){reserve(v.size());for (auto& e : v){push_back(e);}}// 重载vector(size_t n, const T& val = T()){reserve(n);for (size_t i = 0; i < n; i++){push_back(val);}}void clear(){_finish = _start;}// v3 =v1vector<T>& operator=(const vector<T>& v){if (this != &v){clear();reverse(v.size());for (auto& e : v){push_back(e);}}return *this;}// 模板// 任意类型迭代器初始化,要求类型是匹配的template <class InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);++first;}}~vector(){if (_start){delete[] _start;_start = _finish = _end_of_storage = nullptr;}}iterator begin(){return _start;}iterator end(){return _finish;}// 如果第二个const没有,就会导致,对于 const 对象,将无法调用这个 begin 函数。因为 const 对象只能调用 const 成员函数。const_iterator begin() const{return _start;}const_iterator end() const{return _finish;}// 扩容void reserve(size_t n){if (n > capacity()){size_t old_size = size();T* tmp = new T[n];//memcpy(tmp, _start, size() * sizeof(T));// T不一定是内置类型,可能会造成乱码,得深拷贝for (size_t i = 0; i < old_size; i++){tmp[i] = _start[i];}delete[] _start;_start = tmp;_finish = _start + old_size;_end_of_storage = _start + n;}}size_t size() const{return _finish - _start;}size_t capacity() const{return _end_of_storage - _start;}bool empty(){return (_finish == _start);}// 尾插void push_back(const T& x){if (_finish == _end_of_storage){reserve(capacity() == 0 ? 4 : capacity() * 2);}*_finish = x;++_finish;}void pop_back() {assert(!empty());--_finish;}iterator insert(iterator pos, const T& x){assert(pos >= _start);assert(pos <= _finish);if (_finish == _end_of_storage){size_t len = pos - begin();// 防止扩容后导致相对位置发生变化reserve(capacity() == 0 ? 4 : capacity() * 2);pos = begin() + len;}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;--end;}*pos = x;++_finish;return pos;}// 删除指定位置void erase(iterator pos){assert(pos >= _start);assert(pos <= _finish);iterator it = pos + 1;while (it != end()){*(it - 1) = *it;it++;}--_finish;}void resize(size_t n, T val = T()){if (n < size()){_finish = _start + n;}else{reserve(n);while (_finish < _start + n){*_finish = val;++_finish;}}}T operator[](size_t i){assert(i < size());return _start[i];}//void swap(vector<T>& v) void swap(vector& v)// 类里面加不加<T>都行{std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_end_of_storage, v._end_of_storage);}private:iterator  _start = nullptr;iterator  _finish = nullptr;iterator _end_of_storage = nullptr;};// 添加模板template<class T>void print_vector(const vector<T>& v){// 必须加typename// 在没有实例化的内模板(没有int等)中取东西,编译器不能区分这个const_iterator是类型还是静态成员变量(仅是初步检查)typename vector<T>::const_iterator it = v.begin();while (it != v.end()){cout << *it << "	";++it;}cout << endl;for (auto e : v){cout << e << "	";}cout << endl;}template<class Container>void print_container(const Container& v){/*auto it = v.begin();while (it != v.end()){cout << *it << " ";++it;}cout << endl;*/for (auto e : v){cout << e << " ";}cout << endl;}void test_vector1(){vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(4);v.push_back(5);v.insert(v.begin() + 2, 9);for (size_t i = 0; i < v.size(); i++){cout << v[i] << " ";}cout << endl;vector<int>::iterator it = v.begin();while (it != v.end()){cout << *it << " ";++it;}cout << endl;for(auto e : v){cout << e << " ";}cout << endl;cout << endl;print_vector(v);cout << endl;vector<double> vd;vd.push_back(1.1);vd.push_back(2.2);vd.push_back(3.3);vd.push_back(4.4);vd.push_back(5.5);vd.insert(vd.begin() + 2, 9);print_vector(vd);}void test_vector2(){vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(4);v.push_back(5);print_container(v);// 删除所有的偶数auto it = v.begin();while (it != v.end()){if (*it % 2 == 0)v.erase(it);else++it;}print_container(v);}void test_vector3(){vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.push_back(4);v1.push_back(5);v1.resize(10, 9);v1.resize(20);print_container(v1);vector<int> v2(v1);print_container(v2);vector<int> v3(v1.begin(), v1.begin() + 3);print_container(v3);vector<string> v4(10, "11111");print_container(v4);v4.push_back("22222");v4.push_back("22222");v4.push_back("22222");v4.push_back("22222");v4.push_back("22222");print_container(v4);}}

👥总结

vector模拟实现的要点包括:

  1. 迭代器的巧妙运用,通过原生指针实现简单高效的元素访问和操作。
  2. 合理定义和管理私有成员变量start、finish和end_of_storage,实现对存储空间和元素范围的精确控制。
  3. 构造函数涵盖了多种情况,满足不同的初始化需求。
  4. 丰富的元素访问和操作函数,如insert、erase、push_back等,实现了对元素的灵活处理。
  5. 准确获取容量、大小等信息,以及通过reserve、resize等函数进行空间管理。
  6. 赋值运算符重载确保了对象赋值的便捷和安全。

优化方向

  1. 内存管理优化:可以考虑更精细的内存分配策略,减少不必要的内存浪费和频繁的重新分配。
  2. 性能提升:例如在插入和删除操作中,采用更高效的数据移动方式。
  3. 异常处理完善:增强对各种异常情况的处理,提高程序的健壮性。

拓展可能性

  1. 支持更多的模板参数:如增加内存分配器的选择,适应不同的场景需求。
  2. 与其他数据结构的结合:例如与链表或树结构结合,形成更复杂但功能更强大的数据结构。
  3. 多线程安全:使vector在多线程环境下能够安全地进行操作。
  4. 自定义比较器:支持用户自定义元素的比较规则,丰富排序和查找等操作。

本篇博文对 vector的模拟实现 做了一个较为详细的介绍,不知道对你有没有帮助呢

觉得博主写得还不错的三连支持下吧!会继续努力的~

请添加图片描述

相关文章:

【C++】vector 的模拟实现

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &#x1f4e2;本文由 JohnKi 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f4e2;未来很长&#…...

【C++】模版详解

1、概念 C模版分两类&#xff1a;函数模版和类模版 1&#xff09;函数模板的格式 template <class 形参名&#xff0c;class 形参名&#xff0c;......> 返回类型 函数名(参数列表) {函数体 }例如&#xff1a; template <class T> void swap(T& a, T& b…...

应用商店故障(UOS系统)

应用商店故障&#xff08;UOS系统&#xff09; 1. 安装应用商店内的应用无法下载&#xff0c;更新系统时提示依赖关系被破坏&#xff0c;怎么办&#xff1f; 问题描述 安装应用商店内的应用无法下载&#xff0c;更新系统时均提示依赖关系被破坏 解决方案 1、可先建议用户尝试修…...

8月8号前端日报:web在线进行eps32固件升级

最近几天在开发固件更新的功能&#xff0c;学习了不少相关的知识。 在arduino中对esp32进行固件更新&#xff0c;本质是使用esp官方的esptool&#xff0c;使用一个python exe程序&#xff0c;执行一段脚本&#xff0c;该脚本会将固件文件按照对应的位置来写入到esp芯片中。一共…...

win7安装python3.10

到这下载 PythonWin7/3.10.1 at master adang1345/PythonWin7 GitHub...

【Liunx】线程与进程的经典面试题总结

在这个浮躁的时代 只有自律的人才能脱颖而出 -- 《觉醒年代》 线程与进程的面试题总结 1 简述什么是LWP2 简述LWP与pthread_create创建的线程之间的关系3 简述轻量级进程ID与进程ID之间的区别4 请简述什么是线程互斥&#xff0c;为什么需要互斥5 简述你了解的进程间通信方式…...

Python中的 `break` 语句:掌握循环控制的艺术

Python中的 break 语句&#xff1a;掌握循环控制的艺术 下滑即可查看博客内容 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我静心耕耘深度学习领域、真诚分享知识与智慧的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&#xff1a;985高校的普通本硕…...

ES2023(ES14)新特性有什么?

1. Array.prototype.with with 方法返回一个新数组&#xff0c;替换指定索引处的元素 const arr [a, b, c, d]; const res arr.with(2, f); console.log(res);//[a, b, f, d] console.log(arr);//[a, b, c, d] Array.prototype.toSorted 2. Array.prototype.toSorted toS…...

Linux 中的特殊文件权限:SUID、GUID 和 Sticky

注&#xff1a; 机翻&#xff0c;未校。 Special File Permissions in Linux: SUID, GUID and Sticky Bit You see an s instead of x in the file permissions? Linux has some special file permissions called SUID, GUID and Sticky Bit. Know more about them. 在文件权…...

2024 某公司python 面试真题

Q: Can the type of options or labels of switch-case be floating? 在C语言中&#xff0c;switch-case语句的标签必须是整数类型&#xff0c;不能是浮点型。而在Python中&#xff0c;没有switch-case语句&#xff0c;但是可以使用字典来实现类似的功能&#xff0c;而字典的键…...

jwt伪造身份组组组合拳艰难通关

前言 现在的攻防演练不再像以往那样一个漏洞直捣黄龙&#xff0c;而是需要各种组合拳才能信手沾来&#xff0c;但是有时候使尽浑身解数也不能诚心如意。 前期信息收集 首先是拿到靶标的清单 访问系统的界面&#xff0c;没有什么能利用的功能点 首先进行目录扫描&#xff0c;…...

leetcode日记(64)最小覆盖子串

很复杂的题目&#xff0c;无论是思路还是实践都很难… 思路还是看了答案&#xff08;&#xff1f;&#xff09;设定两个指针“框”出一串字符串&#xff0c;初始两个指针都指在s的零位&#xff0c;先移动下指针&#xff0c;直到使框出的字符串中包含t中所有字符串&#xff0c;…...

C语言——编译与链接

目录 引言 翻译环境与运行环境 翻译环境 1.翻译环境的简述 2.编译过程 2.1 预处理&#xff08;预编译&#xff09; 2.2 编译 2.2.1 词法分析 2.2.2 语法分析 2.2.3 语义分析 2.3 汇编 3.链接 运行环境 结束语 引言 C语言编译与链接过程是理解程序如何从代码转化…...

你一定想看的LVS详细介绍及常见模式(NAT,DR,防火墙标记)实验详解

目录 一、什么是LVS 二、LVS的核心思想 三、 LVS的优势 四、LVS的调度算法 4.1. LVS的调度算法类型 4.2. LVS静态调度算法 4.3. LVS动态调度算法 4.4.在4.15版本内核以后新增调度算法 五、LVS软件相关信息 六、ipvsadm命令 七、 LVS的NAT模式实验详解 7.1实验环境 7.…...

嵌入式初学-C语言-十七

#接嵌入式初学-C语言-十六# 函数的递归调用 含义&#xff1a; 在一个函数中直接或者间接调用了函数本身&#xff0c;称之为函数的递归调用 // 直接调用a()->a(); // 间接调用a()->b()->a();a()->b()->..->a();递归调用的本质&#xff1a; 本是是一种循环…...

leetcode数论(2280. 表示一个折线图的最少线段数)-几何

前言 经过前期的基础训练以及部分实战练习&#xff0c;粗略掌握了各种题型的解题思路。现阶段开始专项练习。 数论包含最大公约数(>2个数)、最大公约数性质、最小公倍数、区间范围质因素计数(最下间隔)、质因素分解、判断质数、平方根、立方根、互质、同余等等。 描述 给…...

如何利用 LNMP 搭建 WordPress 站点

作者 乐维社区&#xff08;forum.lwops.cn&#xff09; 许远 在这个信息爆炸的时代&#xff0c;拥有一个能够迅速传达信息、展示个性、并能够与世界互动的在线平台&#xff0c;已成为企业和个人的基本需求。WordPress&#xff0c;以其无与伦比的易用性和强大的扩展性&#xff0…...

“Mutation Observer:让DOM变化尽在掌握

Mutation Observer&#xff08;变动观察者&#xff09; 定义 Mutation Observer是一种JavaScript API&#xff0c;用于异步监测DOM树的变动&#xff0c;包括元素的添加、删除、属性变化等。当DOM发生变动时&#xff0c;它可以触发回调函数&#xff0c;允许你对变动作出响应。 …...

oracle(19c)用户管理

简介 本文介绍 Oracle 中的用户管理&#xff0c;包含以下内容&#xff1a; 概念介绍 系统用户 解锁 hr 用户 创建用户 用户相关案例 使用 Profile 管理用户口令 Oracle 的认证方式 重置管理员(sys)密码 1. 概念介绍 使用前可以自行安装oracle数据库 oracle19c安装&a…...

浅谈安科瑞智慧用电系统在电气火灾中的应用

摘要&#xff1a;为了对电气火灾事故进行预测和预警&#xff0c;同时为了对电气火灾事故的应急救援提供 支持&#xff0c;将智慧用电监控系统应用于电气火灾中。该系统利用物联网、移动互联网、云平台、大数据技术&#xff0c;实现对电气线路电流、漏电、温度、谐波等参数进行…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

CTF show Web 红包题第六弹

提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框&#xff0c;很难让人不联想到SQL注入&#xff0c;但提示都说了不是SQL注入&#xff0c;所以就不往这方面想了 ​ 先查看一下网页源码&#xff0c;发现一段JavaScript代码&#xff0c;有一个关键类ctfs…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...