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

C++:深入剖析vector

希望文章能对你有所帮助,有不足的地方请在评论区留言指正,一起交流学习!

目录

1.vector介绍

1.1.vector与顺序表

1.2.vector与数组

2.vector的使用

2.1.vector的定义

2.2.vector的访问以及遍历(迭代器)

2.3vector的空间容量函数

2.4.vector 增删查改函数

2.5.sort函数


前言:
        本片博客主要介绍vector的成员函数,包含vector常用函数代码演示以及结果分析。包含sort以及find标准库函数。

1.vector介绍

        Vector 是 C++ 标准模板库(STL)中一种非常重要的​​序列容器​​,它本质上是一个能够​​动态增长和缩小​​的数组,在内存中​​连续存储​​元素。因为它封装了内存管理,所以使用起来比原始数组更灵活、更安全。

1.1.vector与顺序表

        vector 的底层数据结构就是顺序表(也常称为 “动态数组”),其设计核心是通过 “连续的内存空间” 存储元素,支持高效的随机访问和动态扩容。

顺序表特征vector 的实现细节
连续内存vector 内部维护一个指向 “连续内存块” 的指针,所有元素依次存放在该内存块中。
随机访问支持通过 [] 运算符或 at() 方法直接按下标访问元素,时间复杂度为 O (1)
逻辑与物理顺序一致插入元素时默认追加到尾部,删除尾部元素时直接缩减有效范围,元素的逻辑顺序始终与内存存储顺序一致
动态扩容当调用 push_back()扩容 等方法导致元素数量超过当前容量(capacity)时,vector 会触发扩容:
1. 申请新内存(通常是原容量的 1.5~2 倍,平衡性能与内存浪费);
2. 将原内存中的所有元素拷贝到新内存;
3. 释放原内存,并更新指针指向新内存。

1. 优势(顺序表的天然优势)

  • 高效随机访问:这是 vector 最核心的优势 —— 访问任意下标元素的时间复杂度为 O (1),远优于链表(如 C++ 的 std::list)。

  • 尾部操作高效push_back()(尾部插入)和 pop_back()(尾部删除)的时间复杂度为 O (1)(仅需移动 “有效元素尾指针”,无需移动其他元素)。

  • 内存局部性好:由于元素存储连续,CPU 缓存能更高效地加载相邻元素(缓存命中效率高),遍历(如 for 循环遍历)速度比链表更快。

2. 局限(顺序表的固有缺陷)

  • 中间 / 头部操作低效:若在 vector 中间或头部插入 / 删除元素(如 insert(pos, val)erase(pos)),需要移动该位置之后的所有元素(以保持内存连续),时间复杂度为 O (n)(n 为元素总数)。

  • 扩容开销:扩容时需要申请新内存、拷贝旧数据、释放旧内存,若元素数量大,会产生明显的时间开销;同时,扩容后原内存会被释放,若存在指向原内存的指针 / 引用,会变成 “野指针”,迭代器失效问题。

  • 内存浪费:为了减少扩容频率,vector 通常会预分配比 “当前元素数量” 更多的内存(即 capacity > size),这部分未使用的内存会造成浪费。

总结

        vector 是 “动态顺序表” 的典型实现—— 它通过连续内存保证高效随机访问,通过动态扩容适应元素数量的变化,同时也继承了顺序表 “中间操作低效”“扩容有开销” 的局限。正因为这一特性,vector 更适合 “频繁随机访问、主要在尾部增删” 的场景,而非 “频繁在中间增删” 的场景(后者更适合链表类容器)。

1.2.vector与数组

        vector 的底层依赖 “动态分配的连续内存块”,而这个内存块在物理存储形式上与静态数组相似(都是连续空间),但管理方式完全不同

  1. 物理存储形式:与静态数组一致
          vector 底层通过一块连续的内存空间存储元素,和静态数组(如 int arr[10])的物理形式完全相同 —— 元素在内存中依次排列,地址连续,因此支持通过 “首地址 + 下标偏移” 实现 O (1) 时间复杂度的随机访问。

  2. 管理方式:与静态数组完全不同
            静态数组的内存是编译期确定或手动分配后固定不变的(大小、地址都不可变),而 vector 的底层内存是动态管理的

    • 内存块的大小(即 capacity)会根据元素数量自动调整(扩容 / 缩容);
    • 当需要扩容时,vector 会重新申请一块更大的连续内存(而非在原内存后追加空间,因为原内存后可能已被其他数据占用),并将旧数据拷贝到新内存,再释放旧内存;
    • 整个过程对用户完全透明,无需手动干预。

            因此,vector 的底层内存虽然 “形式上是连续块(类似静态数组)”,但本质是 “动态分配、可替换的连续块”,而非 “固定不变的静态数组”。

  3. 核心区别:“静态” 与 “动态” 的本质
            静态数组的 “静态” 体现在内存一旦分配就不可变更(大小、地址固定),而 vector 的底层内存可以被 “替换”(通过重新分配新内存块),这使得它能适配元素数量的动态变化。

特性

Vector(动态数组)

传统静态数组

​内存管理​

自动管理,动态分配和释放

手动管理,编译时确定大小

​大小​

动态,可根据需要增长和缩小 (size())

固定,声明后无法改变

​容量​

有容量概念 (capacity()),通常预分配额外空间以优化

无此概念,大小即容量

​插入/删除效率​

尾部操作高效,头部或中间效率低 (O(n))

固定大小,无法直接添加/删除元素

​访问方式​

支持下标 []at()(抛异常)、迭代器

仅支持下标

​传递与返回​

可作为函数参数或返回值,方便传递数据集合

传递时通常退化为指针,丢失大小信息

  总结

        vector 的底层确实依赖 “连续内存块”(这一点与静态数组的物理形式一致),但这块内存是动态管理、可替换的,因此不能简单说是 “最底层是静态数组”而是底层使用动态分配的连续内存块,其物理存储形式与静态数组相似”。

2.vector的使用

         vector在实际中非常的重要,在实际中我们熟悉常 见的接口就可以,下面列出了哪些接口是要重点掌握的。  

       注意:加粗字体标识为重要函数。

2.1.vector的定义

构造函数

接口说明

vector()
无参构造
vector(size_type n, const value_type& val = value_type())
构造并初始化n个val
vector (const vector& x); 
拷贝构造
vector (InputIterator first, InputIterator last);
使用迭代器进行初始化构造

注意:vector是模板类,创建新的对象的时候需要显示实例化

1. 默认构造:创建空vector

std::vector<int> v1; 

2.数量初始化:创建10个元素,每个初始为0

std::vector<int> v2(10); 

3.指定值初始化:创建10个元素,每个都是1

std::vector<int> v3(10, 1); 

4.拷贝构造:创建v3的副本

std::vector<int> v4(v3); 

5.迭代器范围初始化:用数组初始化

int arr[] = {1, 2, 3};
std::vector<int> v5(arr, arr + 3); 

6.C++11 列表初始化:直接使用初始化列表

std::vector<int> v6 = {1, 2, 3, 4, 5};

代码演示:

void test_vector1()
{vector<int> v1;vector<int> v2(10);   vector<int> v3(10, 1);vector<int> v4(v3);int arr[] = { 1,2,3,4,5 };vector<int> v5(arr, arr + 3); // 数组指针就是天然的迭代器//也可以利用string的迭代器初始化vectorstring str("hello world");vector<char> v6(str.begin(), str.end());//其中使用的迭代器初始化不一定是vector的迭代器vector<int> v7 = { 1,2,3,4,5,6 };//迭代器
}

总结:

一般使用就是创建空的vector容器,然后插入数据常用或者拷贝构造函数。

2.2.vector的访问以及遍历(迭代器)

iterator的使用

接口说明

operator[] 

像数组一样访问

at

返回对向量中位置 n 处的元素的引用。该函数会自动检查 n 是否在向量中有效元素的范围内,如果不是( n 大于或等于其大小),则抛出 out_of_range 异常

rbegin + rend

rbegin获取最后一个数据位置的reverse_iterator,rend获取第一个数据前一个位置的

reverse_iterator

begin + end

begin获取第一个数据位置的iterator/const_iterator, end获取最后一个数据的下一个位置

的iterator/const_iterator

1.operator[ ] 

 reference operator[] (size_type n);
const_reference operator[] (size_type n) const;

   reference具体定义为 value_type&。 value_type就是该容器所管理对象的类型也就是模板参数。

T& operator[] (size_type n);
const T& operator[] (size_type n) const;

v

void test_vector2()
{vector<int> v;v.push_back(1);//push_back 为尾插函数 v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);//vector中的数据为 1 2 3 4 5//T& operator[] (size_type n);可以读,可以写for (size_t i = 0; i < v.size(); i++)//size() 为vector中数据的大小{cout << v[i] << " ";}cout << endl;for (size_t i = 0; i < v.size(); i++)//size() 为vector中数据的大小{cout << v[i]++ << " ";// }cout << endl;//const T& operator[] (size_type n) const; 可以读,不可以写//当然对于 const 类型的vector 是不可以修改的const vector<int> v1(v);for (size_t i = 0; i < v.size(); i++)//size() 为vector中数据的大小{cout << v1[i] << " ";}cout << endl;for (size_t i = 0; i < v.size(); i++)//size() 为vector中数据的大小{cout << v1[i]++ << " ";// }cout << endl;
}

说明:

v1为const修饰的常量对象,因此修改的时候会报错

2.at()不常用

reference at (size_type n);
const_reference at (size_type n) const;
  • 和[ ]访问方式是一样的,唯一的不同是会捕捉异常。
  • 访问数据的均会调用函数一个为函数重载函数,一个为构造的at函数

代码演示:

void test_vector3()
{vector<int> v;v.push_back(1);//push_back 为尾插函数 v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);//vector中的数据为 1 2 3 4 5for (size_t i = 0; i < v.size(); i++)//size() 为vector中数据的大小{cout << v.at(i) << " ";}cout << endl;for (size_t i = 0; i < v.size(); i++)//size() 为vector中数据的大小{v.at(i) += 1;cout << v.at(i) << " ";// }cout << endl;}

可以正常的遍历访问,以及修改数据

3.迭代器遍历

  •  begin指向vector的首个数据地址,end指向最后一个数据的下一个地址。
  •  rbegin指向vector的最后一个数据的地址,rend指向首个数据的地址的前一个地址。
  •  对于反向遍历, rit++ 或者++ rit 迭代器会想着rend的方向移动(反向遍历),rit--(--rit)迭代器向容器末尾方向移动,(正向遍历)。可以理解为rbegin就是数据的开始,++操作符,迭代器向数据结束的方向移动。
void test_vector4()
{vector<int> v;v.push_back(1);//push_back 为尾插函数 v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);//vector中的数据为 1 2 3 4 5//正向迭代器vector<int>::iterator  it = v.begin();while (it!= v.end()){cout << (*it) << " ";it++;}cout << endl;//反向迭代器vector<int>::reverse_iterator  rit = v.rbegin();while (rit != v.rend()){cout << (*rit) << " ";rit++;}cout << endl;
}

4.范围for (详细剖析了for的使用)

  • · 范围 for 循环是 C++11 引入的一种简化循环语法,其本质是编译器对迭代器(Iterator)的封装,通过自动获取容器的起始和结束迭代器,简化对容器元素的遍历过程。
  •  范围 for 本质上是迭代器遍历的 “语法糖”,它并没有引入新的遍历机制,而是通过编译器自动处理迭代器的获取、比较、递增和解引用,让代码更简洁。
  • 使用前提:

                标准容器包含list以及vector/map等均定义了begin()和end()方法,返回对应的迭代器。原生数组也是可以的,编译器会自动转换为指针形式的迭代器。自定义类型:有begin()以及end()函数均可以使用范围for。

  • 使用细节:值传递与引用传递

(1)值传递auto elem : container):elem 是容器元素的副本,修改 elem 不会影响原容器。

(2)引用传递auto& elem : container):elem 是容器元素的引用,修改 elem 会直接改变原容器中的元素。当然对于string存储空间较大的类型建议使用引用返回。

(3)常量引用const auto& elem : container):适用于只读场景,避免拷贝大对象的性能开销。

    for (auto& e: v){cout << e << " ";}cout << endl;

2.3vector的空间容量函数

容量空间

接口说明

size

实际元素数量

capacity

预分配容量大小

empyt

判断是否为空

resize(重点)

改变vector的size

reserve (重点)

改变vector的capacity

1.size()函数

size()返回vector当前​​实际存储的元素数量​

    vector<int> v;v.push_back(1);//push_back 为尾插函数 v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);//vector中的数据为 1 2 3 4 5cout << v.size() << endl; // 5

2. capacity函数

capacity()表示vector​​预分配的内存容量​​(元素数量上限),直接调用函数即可使用

cout << v.capacity() << endl;

​动态扩容机制​

对于不同的平台扩容存在差异,主要区别在stl版本,

vs下capacity是按1.5倍增长的,g++是按2倍增长的。 不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义的。vs是PJ版本STL,g++是SGI版本STL。
验证程序:
VS版本(减少内存碎片
void test_vector6()
{size_t sz;vector<int> v;sz = v.capacity();cout << "making v grow:\n";for (int i = 0; i < 100; ++i){v.push_back(i);if (sz != v.capacity()){sz = v.capacity();cout << "capacity changed: " << sz << '\n';}}
}

linux下使用的STL基本是按照2倍方式扩容(提高效率)

内存容量存在的问题

capacity()是vector​​内存管理的核心指标​​,理解其机制可避免:

• 频繁扩容导致的性能骤降(使用reserve开辟空间)

• 迭代器失效引发的崩溃风险(指​​迭代器指向的内存失效或数据位置改变​​)

• 内存浪费问题 (使用reserve存在多开辟的问题)

3.empty

empty()是判断 vector ​​是否无元素​

	cout << v.empty() << endl;

4.reserve

  • 预分配内存空间,避免频繁扩容
  •  不改变元素的数量:不影响 size()仅修改 capacity()。输入的n是要大于size()以及当前的capacity才有扩容的机会的。不要考虑到缩容上,不能使用。
  • 性能价值​​:消除插入操作中的扩容开销
  • 如果 n 大于当前向量容量,则该函数会导致容器重新分配其存储,将其容量增加到 n(或更大)。
v.reserve(100);
cout << v.capacity() << endl;//100

5.resize()

  • 动态调整 size()(元素数量)

  • 初始化控制​​:对新元素赋默认值或指定值

  • 使用说明
void resize (size_type n, value_type val = value_type());
  1. 调整容器的大小,使其包含 n 个元素。
  2. 如果 n 小于当前容器大小,则内容将减少到其前 n 个元素,删除超出的元素(并销毁它们)。
  3. 如果 n 大于当前容器大小,则通过在末尾插入所需数量的元素来扩展内容,以达到 n 的大小。如果指定了 val,则新元素将初始化为 val 的副本,否则,它们将被值初始化。
  4. 如果 n 也大于当前容器容量,则会自动重新分配已分配的存储空间。

代码演示

void test_vector7()
{vector<int> v;v.push_back(1);//push_back 为尾插函数 v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);//vector中的数据为 1 2 3 4 5cout << "原始数据:";cout << v.size() << endl;for (auto& e : v){cout << e << " ";}cout << endl;v.resize(3);cout << "缩小之后:";cout << v.size() << endl;for (auto& e : v){cout << e << " ";}cout << endl;v.resize(10, 1);cout << "扩张之后:";cout << v.size() << endl;for (auto& e : v){cout << e << " ";}cout << endl;
}

特性​

resize(n)

reserve(n)

​核心目标​

控制元素数量(size)

控制内存容量(capacity)

​新增元素​

初始化新增元素

不创建新元素

​内存操作​

可能触发扩容

仅预分配内存

​元素访问​

新元素可立即访问

新空间不可直接访问

        新空间无法访问的原因: vector 的size()没有被reserve改变,访问数据也是随机值不准确的值。
    vector<int> v;v.reserve(10);cout << "reserve: " << v.size() << " ";cout << v.capacity() << endl;v.resize(10);cout << "resize: " << v.size() << " ";cout << v.capacity() << endl;cout << endl;

结果为

2.4.vector 增删查改函数

vector修改函数

接口说明

push_back(重点)尾插
pop_back(重点)尾删
find查找。(算法模块实现,不是vector的成员接口)
insert在指定位置之前插入

erase

删除指定位置的数据

swap

交换两个vector的数据
operator[ ](重点)像数组一样访问
1.push_back  
在其当前最后一个元素之后添加一个新元素。val 的内容被复制到新元素。
演示代码:
    vector<int> v;v.resize(5,5);for (auto& e : v){cout << e << " ";}cout << endl;v.push_back(6);for (auto& e : v){cout << e << " ";}cout << endl;

2.pop_back  

        删除向量中的最后一个元素,有效地将容器大小减少 1。

演示代码:

// 原始数据 5 5 5 5 5 6for (size_t i = 0; i < 5; i++){v.pop_back();}for (auto& e : v){cout << e << " ";}cout << endl;

3.find

        在 C++ 标准库中,find 是一个用于查找元素的通用算法,定义在 <algorithm> 头文件中。它的核心功能是在指定范围内查找第一个与目标值相等的元素,并返回指向该元素的迭代器;如果未找到,则返回范围的结束迭代器(end())。

  • 参数
    • first 和 last:输入迭代器,定义了查找的范围 [first, last)(左闭右开,包含 first 指向的元素,不包含 last 指向的元素)。
    • value:要查找的目标值。
  • 返回值
    • 若找到匹配元素,返回指向该元素的迭代器;
    • 若未找到,返回 last 迭代器。

演示代码

void test_vector13()
{vector<int>  v = { 1,2,3,4,5,6,7,8,9,10 };auto pos = find(v.begin(), v.end(), 4);if (pos!=v.end()){v.erase(pos);}for (auto& e : v){cout << e << " ";}cout << endl;
}

4.insert

(1)单元素插入

iterator insert (iterator position, const value_type& val);

        功能:在 position 指向的位置之前插入一个值为 val 的元素
        返回值:指向新插入元素的迭代器

(2)填充插入 (fill)

void insert (iterator position, size_type n, const value_type& val);

        功能:在 position 指向的位置前插入 n 个值为 val 的元素
        无返回值
(3)范围插入 (range)


template <class InputIterator>
void insert (iterator position, InputIterator first, InputIterator last);

        功能:在 position 指向的位置前插入 [first, last) 范围内的所有元素
        无返回值

演示代码

    vector<int> v;v.reserve(50);for (size_t i = 1; i < 5; i++) {v.push_back(i);}for (auto& e : v){cout << e << " ";}cout << endl;//在第三个位置插入一个7v.insert(v.begin() + 2, 7);for (auto& e : v){cout << e << " ";}cout << endl;//在第五个位置插入3个 6v.insert(v.begin() + 4, 3, 6);for (auto& e : v){cout << e << " ";}cout << endl;

第三种方式使用较少,这里将使用数组为例

    //在第五个位置插入3个 8int a[] = { 8,8,8 };v.insert(v.begin() + 4, a, a + 3);for (auto& e : v){cout << e << " ";}cout << endl;

存在迭代器失效问题,将在后续分析。

5.erase

在vector中删除单个元素(位置)或一系列元素([first,last))。
由于vector使用数组作为其底层存储,因此擦除有效数据以外的位置的元素会导致程序崩溃。操作较为低效。

iterator erase (iterator position);
iterator erase (iterator first, iterator last);

演示代码:

void test_vector11()
{vector<int> v;v.reserve(50);for (size_t i = 1; i < 10; i++){v.push_back(i);}for (auto& e : v){cout << e << " ";}cout << endl;v.erase(v.begin());for (auto& e : v){cout << e << " ";}cout << endl;//删除前4个v.erase(v.begin(), v.begin() + 4);for (auto& e : v){cout << e << " ";}cout << endl;
}

        删除数据为左开右闭,begin()+ 4指向第五个元素,但是只删除了前四个元素,因此是左开右闭区间。

6.swap

  • 将容器的内容交换为 x 的内容,x 是相同类型的另一个vector对象,大小可能不同。
  • std算法库中也存在swap函数。
void swap (vector& x);
void test_vector12()
{vector<int>  v1;v1.resize(5, 1);vector<int>  v2;v2.resize(5, 2);cout << "交换前:" << endl;for (auto& e : v1){cout << e << " ";}cout << endl;for (auto& e : v2){cout << e << " ";}cout << endl;v1.swap(v2);cout << "交换后:" << endl;for (auto& e : v1){cout << e << " ";}cout << endl;for (auto& e : v2){cout << e << " ";}cout << endl;
}

2.5.sort函数

        C++ 标准库中的sort函数提供了两种主要形式,用于满足不同的排序需求。这两种形式都定义在<algorithm>头文件中,并且都要求使用随机访问迭代器(RandomAccessIterator),这意味着它们可以用于vectorarray、原生数组等支持随机访问的容器。

默认形式

template <class RandomAccessIterator>
void sort (RandomAccessIterator first, RandomAccessIterator last);
  •  这种形式的sort函数使用默认的升序排序,通过元素类型的<运算符进行比较。即对于范围内的元素ab,如果a < btrue,则a会被排在b之前。

自定义比较形式 

template <class RandomAccessIterator, class Compare>
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
  •  这种形式允许通过第三个参数comp指定自定义的比较规则。comp是一个比较函数(或函数对象),它接受两个与容器元素类型相同的参数,并返回一个bool值。如果返回true,表示第一个参数应该排在第二个参数之前。

降序的实现

void sort (RandomAccessIterator first, RandomAccessIterator last, greater<int>());
  •  在 C++ 中,std::greater是标准库提供的一个函数对象(functor),定义在<functional>头文件中,可直接作为sort函数的第三个参数,实现降序排序(从大到小)。
  • std::greater的工作原理是:对于两个元素abstd::greater<T>()(a, b)会返回a > b的结果,即当a大于b时,a应排在b前面。

演示代码:

void test_vector14()
{vector<int> v{ 2,58,96,25,12,5,19,8,7 };cout << "原始:";for (auto& e : v){cout << e << " ";}cout << endl;sort(v.begin(), v.end());cout << "升序:";for (auto& e : v){cout << e << " ";}cout << endl;vector<int> v1{ 2,58,96,25,12,5,19,8,7 };sort(v1.begin(), v1.end(), greater<int>());cout << "降序:";for (auto& e : v1){cout << e << " ";}cout << endl;vector<int> v2{ 2,58,96,25,12,5,19,8,7 };sort(v2.rbegin(), v2.rend());//反向迭代器排的是反向顺序cout << "降序:";for (auto& e : v1){cout << e << " ";}cout << endl;
}

为什么反向迭代器排出来的是降序?

  1. 反向迭代器的行为

    • rbegin()指向容器的最后一个元素(相当于正向迭代器的end() - 1)。
    • rend()指向容器的第一个元素的前一个位置(相当于正向迭代器的begin() - 1)。
    • 反向迭代器的++操作等价于正向迭代器的--操作(即向容器开头移动)。
  2. sort 函数的排序逻辑
    sort函数始终按照比较器的规则对迭代器范围内的元素进行升序排序(默认使用<运算符)。当传入反向迭代器时:

    • 排序范围变成了[rbegin(), rend()),即从容器末尾到开头的 “反向区间”。
    • sort对这个 “反向区间” 进行升序排序,等价于对原容器进行降序排序。

问题总结

         排序从rbegin开始,排的是升序,从rbegin到rend是升序,因此反向的rend到rbegin为降序。


文章转载自:

http://3z1ZF9xa.qzsmz.cn
http://oWG6Rxhf.qzsmz.cn
http://uzW9keha.qzsmz.cn
http://1p1k8D4G.qzsmz.cn
http://xrIPgrKK.qzsmz.cn
http://5MlyriHr.qzsmz.cn
http://BAF8htdJ.qzsmz.cn
http://g3OktHWP.qzsmz.cn
http://DbQrh12L.qzsmz.cn
http://3CsRID04.qzsmz.cn
http://rUOkUpHp.qzsmz.cn
http://u9W8NsSA.qzsmz.cn
http://StSblFAN.qzsmz.cn
http://WoVa0LW8.qzsmz.cn
http://RU9DDCIp.qzsmz.cn
http://PvUybUpG.qzsmz.cn
http://0Cx1jCPU.qzsmz.cn
http://a9s0FXw7.qzsmz.cn
http://iiUZZ5bM.qzsmz.cn
http://xj5FSuZc.qzsmz.cn
http://FeIj2HZf.qzsmz.cn
http://4g6D0foy.qzsmz.cn
http://SjqY0YRp.qzsmz.cn
http://vhvzin3j.qzsmz.cn
http://pTwgVqzg.qzsmz.cn
http://e5xK8Bbp.qzsmz.cn
http://ntGFh02E.qzsmz.cn
http://4mgBDmyo.qzsmz.cn
http://ikwOvTQn.qzsmz.cn
http://ejmUurPB.qzsmz.cn
http://www.dtcms.com/a/370961.html

相关文章:

  • Arazzo AI监考Agent API实战教程
  • *和->的区别
  • MySQL中有哪些锁
  • 什么是云手机?
  • 基于FPGA的电梯控制系统设计(论文+源码)
  • Vllm-0.10.1:vllm bench serve参数说明
  • 华为悦盒EC6108V9/EC6108V9U/EC6108V9C_MV100(pub普通版/CA高安版)卡刷和强刷固件包
  • JVM中常见的GC垃圾收集器
  • Rsyslog日志采集
  • 代理连接性能优化:提升网络效率的关键技术与实践
  • NV308NV309美光固态闪存NW388NW504
  • C++中的栈
  • 手撕C++ list容器:从节点到完整双向链表实现
  • [Windows] AdGuard.v7.21.5089.0 中文直装电脑版
  • Skia如何渲染 Lottie 动画
  • 打工人日报#20250906
  • 基于GOA与BP神经网络分类模型的特征选择方法研究(Python实现)
  • 【完整源码+数据集+部署教程】苹果实例分割检测系统源码和数据集:改进yolo11-AggregatedAtt
  • [Upscayl图像增强] 多种AI处理模型 | 内置模型与自定义模型
  • RK3568 Trust
  • ECharts Gallery:Apache官方数据可视化模板库,助你快速制作交互图表并实现深度定制
  • 【LeetCode热题100道笔记】二叉搜索树中第 K 小的元素
  • HMI(人机界面)
  • 懒加载的概念
  • panther X2 armbian24 安装宝塔(bt)面板注意事项
  • 少儿配音教育:广州声与色在线科技有限公司打造趣味课程,助力青少年语言能力提升
  • 零基础学习数据采集与监视控制系统SCADA
  • springboot vue sse消息推送,封装系统公共消息推送前后端方法
  • 万字长文详解 MyCat 分表分库:从 0 到 1 构建高可用订单系统
  • Transformer架构(详解)