STL 剖析

STL 六大组件

「STL 六大组件的交互关系」

  • Container 通过 Allocator 取得数据储存空间
  • Algorithm 通过 Iterator 存取 Container 内容
  • Functor 可以协助 Algorithm 完成不同的策略变化
  • Adapter 可以修饰或套接 Functor、Iterator

配置器(allocator)

配置器:负责空间配置与管理,从实现的角度来看,配置器是一个实现了动态空间配置、空间管理、空间释放的 class template。

空间配置器:整个 STL 的操作对象(所有的数值)都存放在容器之内,而容器一定需要配置空间以存放内容。

具有次配置力(sub-allocation)的 SGI 空间配置器

SGI STL 空间配置器的结构

SGI STL 的配置器,其名称是 alloc 而不是 allocator,而且不接受任何参数。

SGI STL 的每一个容器都已经指定其缺省的空间配置器为 alloc。

template <class T, class Alloc = alloc>  // 缺省使用 alloc 为配置器class vector {...};vector<int, std::alloc> iv;

  • <defalloc.h>----SGI 标准的空间配置器,std::allocator

allocator 只是基层内存配置/释放行为(::operator::new 和 ::operator::delete)的一层薄薄的包装,并没有考虑到任何效率上的强化。

  • SGI 特殊的空间配置器,std::alloc
    • <stl_construct.h>:定义了全局函数 construct() 和 destroy(),负责对象的构造和析构。
    • <stl_alloc.h>:定义了一、二级配置器,配置器名为 alloc。
    • <stl_uninitialized.h>:定义了全局函数,用来填充(fill)或复制(copy)大块内存数据。
  • 构造和析构基本工具

具体看 <stl_construct.h> 源码,功能是构造和析构操作。

  • 空间的配置和释放,std::alloc
    • 向 system heap 要求空间
    • 考虑多线程(multi-threads)状态
    • 考虑内存不足时的应变措施
    • 考虑过多 “小型区块” 可能造成的内存碎片问题

对象构造前的空间配置 和 对象析构后的空间释放,具体看 <stl_alloc.h>。

SGI STL 空间配置器的分析

考虑到小型区块可能造成内存碎片问题,SGI 采用两级配置器,第一级配置器直接使用 malloc() 和 free() 实现;第二级配置器使用 memory pool 内存池管理。

第二级配置器的原理:

  • 当配置区块超过 128 bytes,就使用第一级配置器
  • 当配置区块小于 128 bytes,使用内存池管理

enum {_ALIGN = 8};  // 小型区块的上调边界

enum {_MAX_BYTES = 128}; // 小区区块的上限

enum {_NFREELISTS = 16}; // _MAX_BYTES/_ALIGN  free-list 的个数

// free-list 的节点结构,降低维护链表 list 带来的额外负担

union _Obj {union _Obj* _M_free_list_link;  // 利用联合体特点char _M_client_data[1];    /* The client sees this. */};

static _Obj* __STL_VOLATILE _S_free_list[_NFREELISTS];  // 注意,它是数组,每个数组元素包含若干相等的小额区块

其中 free-list 是指针数组,16 个数组元素,就是 16 个 free-list,各自管理大小分别为 8, 16, 24, 32,...128 bytes(8 的倍数)的小额区块。

小额区块的结构体 union _Obj 使用链表连接起来。

配置器负责配置,同时也负责回收。

迭代器(iterator)

迭代器:扮演容器与算法之间的桥梁,是所谓的 “泛型指针”,共有五种类型,以及其它衍生变化。从实现的角度来看,迭代器是一种将 operator*,operator->,operator++,operator-- 等指针相关操作予以重载的 class template。 所有 STL 容器都附带有自己专属的迭代器。 native pointer 也是一种迭代器。

迭代器(iterator) 是一种 smart pointer

迭代器是一种行为类似指针的对象,而指针的各种行为中最常见的用途是 dereference 和 member access。迭代器最重要的就是对 operator* 和 operator->进行重载工作。

auto_ptr:用来包装原生指针(native pointer)的对象,在头文件 中定义。

为什么每一种 STL 容器都提供有专属迭代器的缘故。

主要是暴露太多细节,所以把迭代器的开发工作交给容器去完成,这样所有实现细节可以得到封装,不被使用者看到。

迭代器相应类型(associated types)

迭代器所指对象的类型。

利用 function template 的参数推导机制,只能推导出参数的类型,无法推导出函数返回值类型。

迭代器相应类型有五种:

  • value type
  • difference type
  • pointer
  • reference
  • iterator category

Traits 编程技术

traits 意为 “特性”,扮演 “特性萃取机” 角色,萃取各个迭代器的特性(相应类型)。

template partial specialization 模板偏特化:针对 template 参数更进一步的条件限制所设计出来的一个特化版本,本身仍然是 template。

tempalte<typename I>struct iterator_traits{typedef typename I::iterator_category  iterator_category;typedef typename I::value_type  value_type;typedef typename I::difference_type  difference_type;typedef typename I::pointer  pointer;typedef typename I::reference  reference;};
  • 迭代器相应类型之一:value type

value type 就是迭代器所指对象的类型。

template <class T>typename iterator_traits<I>::value_type func(I ite){return *ite;}
  • 迭代器相应类型之二:difference type

difference type 用来表示两个迭代器之间的距离。

template <class I, class T>typename iterator_traits<I>::difference_type cout(I first, I last, const T& value){typename iterator_traits<I>::difference_type n = 0;for (; first != last; ++first){++n;}return n;}
  • 迭代器相应类型之三:reference type

在 c++ 中,函数如果要传回左值,都是以 by reference 的方式进行,所以如果 p 是一个迭代器,它的 value type 是 T ,那么*p 应该是T& (即reference typ·e)

  • 迭代器相应类型之四:pointer type
    •      迭代器相应类型之五:iterator_category
      • 输入迭代器 (InputIterator) 是能从所指向元素读取的迭代器 (Iterator) 。输入迭代器 (InputIterator) 仅保证单趟算法的合法性。
      • 输出迭代器 (OutputIterator) 是能写入所指元素的迭代器 (Iterator) 。
      • 向前迭代器 (ForwardIterator) 是一种能从所指向元素读取数据的迭代器 (Iterator) 。
      • 双向迭代器 (BidirectionalIterator) 是能双向移动(即自增与自减)的向前迭代器 (ForwardIterator) 。
      • 随机访问迭代器 (RandomAccessIterator) 是能在常数时间内移动到指向任何元素的双向迭代器 (BidirectionalIterator) 。

总结

traits 本质是什么?

多一层间接性,换来灵活性。

iterator_traits 负责萃取迭代器的特性,__type_traits 负责萃取类型的特性

容器(container)

容器:包括序列式容器和关联式容器;即各种数据结构,如 vector,list,deque,set,map 等用来存储数据;从实现的角度来看,STL 容器是一种 class template。

任何特定的数据结构都是为了实现某种特定的算法。

序列式容器(sequence container)

  • array (C++ 提供,build-in)
  • vector
  • heap (内含一个 vector)
  • priority-queue (内含一个 heap)
  • list
  • slist (非标准)
  • deque
  • stack (内含一个 deque) (adapter 配接器)
  • queue (内含一个 deque) (adapter 配接器)

怎么理解序列式容器,其中的元素都可序(ordered), 但未必有序(sorted)?

ordered 是容器集合被排序,可以使用指定的顺序去遍历集合。 sorted 是一个容器集合根据某些规则确定排序的。

关联式容器(associative container)

  • RB-tree (非公开)
  • set (内含一个 RB-tree)
  • map (内含一个 RB-tree)
  • multiset (内含一个 RB-tree)
  • multimap (内含一个 RB-tree)
  • hashtable (非标准)
  • hash_set (内含一个 hashtable) (非标准)
  • hash_map (内含一个 hashtable) (非标准)
  • hash_multiset (内含一个 hashtable) (非标准)
  • hash_multimap (内含一个 hashtable) (非标准)

熟悉关联式容器,需要有 RB-tree(红黑树原理) 和 hash table(哈希表原理) 基础。

算法(algorithm)

算法:各种常用算法如 sort,search,copy,erase 等,从实现的角度来看,STL 算法是一种 function template。

所有泛型算法的前两个参数都是一对迭代器,STL 习惯使用前闭后开的区间,[first, last)。

最后一个元素的下一位置,称为 end()。

数值的传递由 pass-by-value 改为 pass-by-reference,好处是,在模板中,参数的类型可以任意,当对象一大,传递成本便会上升,所以用 pass-by-reference 可以节省空间。

数值算法 <stl_numeric.h>

STL 将数值算法的内部实现放在 <stl_numeric.h> 中,用户调用数值算法的接口,需要包含 头文件。  

元素累加 accumulate

算法 accumulate 用来计算 init 和 [first, last) 内所有元素的总和。

相邻元素的差值 adjacent_difference

算法 adjacent_difference 用来计算 [first, last) 中相邻元素的差值。

内积 inner_product

算法 inner_product 计算 [first1, last1) 和 [first2, first2 + (last1 - first1)) 的一般内积。 

局部求和 partial_sum

算法 partial_sum 用来计算局部求和。

幂次方 power

算法 power 用来计算某数的 n 幂次方。

递增 iota

在某区间 [first, last) 填入某指定值 value 的递增序列。

基本算法 <stl_algobase.h>

判断两个区间是否相等 equal

如果两个序列在 [first, last) 区间内相等,equal() 返回 true。

注意,如果第二个序列的元素比较多,多出来的元素不予考虑,只要与第一个序列的元素相等,就返回 true。

改填元素 fill

将 [first, last) 内的所有元素改填新值。

改填元素的值 n 次 fill_n

将 [first, last) 内的前 n 个元素改填新值,返回的迭代器指向被填入的最后一个元素的下一位置。

元素互换 iter_swap

将两个 Forwarditerators 所指的对象对调。

以字典顺序进行比较 lexicographical_compare

以 "字典排列方式" 对两个序列 [first1, last1) 和 [first2, last2) 进行比较。

最大值 max

取两个对象的较大值。

最小值 min

取两个对象的最小值。

找出不匹配的点 mismatch

用来平行比较两个序列,指出两者之间的第一个不匹配点。

交换 swap

该函数用来交换两个对象的内容。

复制 copy

copy 算法可将输入区间 [first, last) 内的元素复制到输出区间 [result, result + (last-first)) 内。

逆向复制 copy_backward

将 [first, last) 区间内的每一个元素,以逆行的方向复制到以 result-1 为起点,方向亦为逆行的区间上。

set 相关算法

  • 并集 set_union

算法 set_union 可构造 S1、S2 之并集(S1 U S2),此集合内含 S1 或 S2 内的每一个元素。其中 S1、S2 及其并集都是以排序区间表示。

  • 交集 set_intersection

算法 set_intersection 可构造 S1、S2 之交集。

  • 差集 set_difference

算法 set_difference 可构造 S1、S2 之差集。此集合内含出现于 S1 但不出现于 S2 的每一个元素。

  • 对称差集 set_symmetric_difference

算法 set_symmetric_difference 可构造 S1、S2 之对称差集。此集合内容出现于 S1 但不出现于 S2 以及 出现于 S2 但不出现 S1 的每一个元素。

heap 算法

头文件 <stl_heap.h>

  • make_heap() 建堆
  • pop_heap() 从堆中取出一个元素
  • push_heap() 将一个元素推进堆内
  • sort_heap() 对堆排序

其它算法 <stl_algo.h>

定义于 SGI <stl_algo.h> 内的所有算法。

查找相邻而重复的元素 adjacent_find

对一个序列,查找相邻元素值相等的第一个元素。

计数 count

将 [first, last) 区间内的每一个元素拿来和指定值 value 比较,并返回与 value 相等的元素个数。

在特定条件下计数 count_if

将指定操作(一个仿函数) pred 实施于 [first, last) 区间内的每一个元素身上,并将造成 pred 计算结果为 true 的所有元素的个数返回。

循环查找 find

循环查找 [first, last) 内的所有元素,找出第一个匹配条件的,返回指向该元素的迭代器。

在特定条件下循环查找 find_if

根据指定的 pred 运算条件,循环查找 [first, last) 内的所有元素,找出第一个令 pred 运算结果为 true,返回指向该元素的迭代器。

查找某个子序列的最后一次出现点 find_end

在序列一 [first, last) 所涵盖的区间中,查找序列二 [first, last) 的最后一个出现点。

查找某些元素的第一次出现点 find_first_of

本算法以 [first2, last2) 区间内的某些元素作为查找目标,寻找在 [first1, last1) 区间内的第一次出现地点。

对区间内的每一个元素进行某操作 for_each

将仿函数 f 作用于 [first, last) 区间内的每一个元素上。

以特定操作之运算结果填充特定区间内的元素 generate

将仿函数 gen 的运算结果赋值给 [first, last) 区间内的所有元素上。

以特定操作之运算结果填充 n 个元素内容 generate_n

将仿函数 gen 的运算结果填写在从迭代器 first 开发的 n 个元素身上。

应用于有序区间 includes

S1 和 S2 必须是有序集合,其中的元素可以重复,判断 S1 是否包含于 S2。includes 算法可供用户选择采用 less 或 greater 进行两元素的大小比较。

最大值所在位置 max_element

这个算法返回一个迭代器,指向序列之中数值最大的元素。

应用于有序区间的合并操作 merge

将两个经过排序的集合 S1 和 S2,合并起来置于另一段空间。所得结果也是一个有序序列。

最小值所在位置 min_element

这个算法返回一个迭代器,指向序列之中数值最小的元素。

分割 partition

partition 将区间 [first, last) 中的元素重新排列。所有被一元条件运算 pred 判定为 true 的元素,都会被放在区间的前段,被判定为 false 的元素,都会被放在区间的后段。

如果需要保留原始相对位置,应使用 stable_partition。

移除并不删除 remove

移除 [first, last) 之中所有与 value 相等的元素,这一算法并不真正从容器中删除那些元素,而是将每一个不与 value 相等的元素轮番赋值给 first 之后的空间。

移除某类元素并将结果复制到另一容器 remove_copy

移除 [first, last) 之中所有与 value 相等的元素。它并不真正从容器中删除那些元素,而是将结果复制到一个以 result 标示起始位置的容器身上。

有条件地删除某类元素 remove_if

移除 [first, last) 区间内所有被仿函数 pred 认定为 true 的元素,每一个不符合 pred 条件的元素都会被轮番赋值给 first 之后的空间。

有条件地删除某类元素并将结果复制到另一容器 remove_copy_if

移除 [first, last) 区间内所有被仿函数 pred 认定为 true 的元素,它并不真正从容器中删除那些元素,而是将结果复制到一个以 result 标示起始位置的容器身上。

替换某类元素 replace

将 [first, last) 区间内的所有 old_value 都以 new_value 取代。

替换某类元素,并将结果复制到另一个容器 repalce_copy

唯一不同的是新序列会被复制到 result 所指的容器中。

有条件地替换 replace_if

将 [first, last) 区间内的所有被 pred 评估为 true 的元素,都以 new_value 取而代之。

有条件地替换,并将结果复制到另一个容器 replace_copy_if

行为与 replace_if() 类似,新序列会被复制到 result 所指的区间内。

反转元素次序 reverse

将序列 [first, last) 的元素在原容器中颠倒重排。

反转元素次序并将结果复制到另一个容器 reverse_copy

行为与 reverse() 类似,新序列会被复制到 result 所指的容器中。

旋转 rotate

将 [first, middle) 内的元素和 [middle, last) 内的元素互换,middle 所指的元素会成为容器的第一个元素。

旋转,并将结果复制到另一个容器 rotate_copy

行为与 rotate_copy() 类似,新序列会被复制到 result 所指的容器中。

查找某个子序列 search

在序列一 [first1, last1) 所涵盖的区间中,查找序列二 [first2, last2) 的首次出现点。

查找连续发生 n 次的子序列 search_n

在序列 [first, last) 所涵盖的区间中,查找连续 count 个符合条件之元素所形成的子序列,并返回一个迭代器指向该子序列起始处。

指定区间交换 swap_ranges

将 [first1, last1) 区间内的元素与从 first2 开始、个数相同的元素互相交换。这两个序列可位于同一容器中,也可位于不同的容器中。

以两个序列为基础,交互作用产生第三个序列 transform

transform() 两个版本都执行结果放进迭代器 result 所标示的容器中。

将重复的元素删除,只保留一个 unique

算法 unique 能够移除重复的元素。每当在 [first, last) 内遇到重复元素群,它便移除该元素群中第一个以后的所有元素。

将重复的元素删除,只保留一个, 并复制 result 中unique_copy

算法 unique_copy 可从 [first, last) 中将元素复制到以 result 开头的区间上。

lower_bound (应用于有序区间)

二分查找,在已排序的 [first, last) 中的寻找元素 value,返回位置。

upper_bound (应用于有序空间)

二分查找,在已排序的 [first, last) 中的寻找元素 value,与 lower_bound 区别是返回查找值的位置。

二分查找 binary_search (应用于有序空间)

二分查找法,在已排序的 [first, last) 中的寻找元素 value,查找到,返回 true,否则 false。

求下一个排列组合 next_permutation

next_permutation() 获取 [first, last) 所标示之序列的下一个排列组合。

实现原理:

在当前序列中,从尾端往前寻找两个相邻元素,前一个记为 *i,后一个记为 *ii,并且满足 *i < *ii。然后再从尾端寻找另一个元素 *j,如果满足 *i < *j,即将第 i 个元素与第 j 个元素对调,并将第 ii 个元素之后(包括ii)的所有元素颠倒排序,即求出下一个序列了。

求上一个排列组合 prev_permutation

prev_permutation() 获取 [first, last) 所标示之序列的上一个排列组合。

实现原理:

在当前序列中,从尾端往前寻找两个相邻元素,前一个记为 *i,后一个记为 *ii,并且满足 *i > *ii。然后再从尾端寻找另一个元素 *j,如果满足 *i > *j,即将第 i 个元素与第 j 个元素对调,并将第 ii 个元素之后(包括ii)的所有元素颠倒排序,即求出上一个序列了。

随机重排元素 random-shuffle

这个算法将 [first, last) 的元素次序随机重排, 在 N!种可能的元素排列顺序中随机选出一种,此处 N 为 last-first。

局部排序 partial_sort/partial_sort_copy

本算法接受一个 middle 迭代器(位于序列 [first, last) 之内),然后重新安排 [first, last),使序列中的 middle-first 个最小元素以递增顺序排序,置于 [first, middle)内。其余 last-middle 个元素安置于 [middle, last) 中,不保证有任何特定顺序。

排序算法 sort

STL 的 sort 算法,数据量大时采用 Quick Sort,分段递归排序,当数据量小于某个门槛(5-20),就改用 Insertion Sort。

Insertion Sort

插入排序是以双层循环的形式进行。时间复杂度为 O(N^2)。

将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。

Quick Sort

平均时间复杂度为 O(NlogN),最坏情况下将达 O(N^2)。

STL 早期采用 Quick Sort,现在 SGI STL 改用 IntroSort(极类似 median-of-three QuickSort 的一种排序算法)。

递归

Median-of-Three(三点中值) 中间值

Partitioning 分割

SGI STL sort

混合式排序算法,Introspective Sorting,当做 Partitioning 操作,有恶化为二次行为的倾向时,改用 Heap Sort,使其效率维持在 Heap Sort 的 O(NlogN)。

用 __lg() 控制分割恶化的情况:

// 找出 2^k <= n 的最大值 ktemplate <class size>inline Size __lg(Size n) {Size k;for (k = 0; n > 1; n >>= 1)++k;return k;}

最多允许分割 2k 层;

混合式排序思想:

  • 先判断序列大小,当大于阈值 __stl_threshold(16),再检查分割层次,如果分割层次超过指定值 0,就改用 Heap Sort完成;
  • 在大于阈值 __stl_threshold(16),分割层次不为 0,就继续使用 Quick Sort;
  • 如果小于阈值,则用插入排序;

equal_range(应用于有序区间)

算法 equal_range 是二分查找法的一个版本,试图在已排序的 [first, last) 中寻找 value。

返回一个上下区间。

inplace_merge(应用于有序区间)

合并 并且 就地排序

nth_element

使第 n 大元素处于第 n 位置(从0开始,其位置是下标为 n的元素),并且比这个元素小的元素都排在这个元素之前,比这个元素大的元素都排在这个元素之后,但不能保证他们是有序的。

归并排序 merge sort

Merge Sort 的复杂度为 O(NlogN)。需要借用额外的内存。底层是调用 inplace_merge 实现。

仿函数/函数对象(functor/function object)

仿函数/函数对象:行为类似函数,可作为算法的某种策略,从实现的角度来看,仿函数是一种重载了 operator() 的 class 或 class template。STL 仿函数应该有能力被函数配接器(function adapter)修饰,为了拥有配接能力,每一个仿函数必须定义自己的相应类型。

以操作数的个数划分,可分为一元和二元仿函数

  • unary_function
unary_function 用来呈现一元函数的参数类型和返回值类型。// 一元函数的参数类型和返回值类型template <class _Arg, class _Result>struct unary_function {typedef _Arg argument_type;typedef _Result result_type;};binary_function
binary_function 用来呈现二元函数的第一参数类型、第二参数类型,以及返回值类型。// 二元函数的第一个参数类型和第二个参数类型,以及返回值类型template <class _Arg1, class _Arg2, class _Result>struct binary_function {typedef _Arg1 first_argument_type;typedef _Arg2 second_argument_type;typedef _Result result_type;};

功能划分

算法类(Arithmetic)仿函数

STL 内建的 "算术类仿函数",支持加法、减法、乘法、除法、模数和求反运算符。,

关系运算类(Relational)仿函数

STL 内建的 "关系运算类仿函数" 支持等于、不等于、大于、大于等于、小于、小于等于六种运算。

逻辑运算类(Logical)仿函数

STL 内建的 "逻辑运算类仿函数" 支持了逻辑运算种的 And、Or、Not 三种运算。

identity、select、project

将其参数原封不动地传回。为了间接性——间接性是抽象化的重要工具。

适配器(adapter)

适配器:一种用来修饰容器、仿函数或迭代器接口的东西。例如,STL 提供的 queue 和 stack,虽然看似容器,其实只能算是一种容器适配器,因为它们的底部完全借助 deque,所有操作都由底层的 deque 供应。改变 functor 接口者,称为 function adapter等。

适配器(adapter) 在 STL 组件的灵活组合运用功能上,扮演者转换器的角色。

应用于容器,container adapter

STL 提供的两个容器 queue 和 stack,它们修饰 deque 的接口而形成的。

应用于迭代器,iterator adapter

STL 提供了许多应用于迭代器的适配器。

insert iterator

插入迭代器内部都维护有一个容器,容器当然有自己的迭代器,当客户端对插入迭代器做赋值操作时,就在插入迭代器中被转为对该容器的迭代器做插入操作。

back_insert_iterator

用于在容器尾部插入的迭代器适配器。

front_insert_iterator

用于在容器头部插入的迭代器适配器。

reverse iterator

将迭代器的移动行为倒转。以尾到头的方向来处理序列中的元素。

stream iterator

将迭代器绑定到一个 stream 对象身上,绑定到 istream 对象为 istream_iterator,拥有输入能力。

绑定到 ostream 对象为 ostream_iterator,拥有输出能力。

应用于仿函数,function adapter

对返回值进行逻辑否定:not1, not2

对参数进行绑定:bind1st, bind2nd

用于函数合成:compose1, compose2

用于函数指针:ptr_fun

用于成员函数指针:mem_fun, mem_fun_ref

来源于  GitHub  整理

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

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

相关文章

Y3编辑器教程8:资源管理器与存档、防作弊设置

文章目录 一、资源管理器简介1.1 界面介绍1.2 资源商店1.3 AI专区1.3.1 AI文生图1.3.2 AI图生图1.3.3 立绘头像 二、导入导出2.1 文件格式2.2 模型导入2.2.1 模型制作后导出2.2.2 模型文件导入Y3编辑器2.2.3 Y3编辑器角色、装饰物模型要求 2.3 纹理导入2.4 材质贴图2.4.1 材质支…

DL作业11 LSTM

习题6-4 推导LSTM网络中参数的梯度&#xff0c; 并分析其避免梯度消失的效果 LSTM&#xff08;长短期记忆网络&#xff09;是一种特殊的循环神经网络&#xff08;RNN&#xff09;&#xff0c;旨在解决普通 RNN 在处理长序列时遇到的梯度消失和梯度爆炸问题。它通过设计多个门…

面试题整理9----谈谈对k8s的理解1

谈谈对k8s的理解 1. Kubernetes 概念 1.1 Kubernetes是什么 Kubernetes 是一个可移植、可扩展的开源平台&#xff0c;用于管理容器化的工作负载和服务&#xff0c;方便进行声明式配置和自动化。Kubernetes 拥有一个庞大且快速增长的生态系统&#xff0c;其服务、支持和工具的…

解决MySQL安装难题:vcruntime140_1.dll文件丢失修复指南

在安装MySQL的过程中&#xff0c;用户可能会遇到一个常见的问题&#xff1a;“找不到vcruntime140_1.dll&#xff0c;无法继续执行代码”。这个错误提示表明系统缺少一个关键的动态链接库文件&#xff0c;这对于运行依赖于它的应用程序至关重要。本文将详细介绍vcruntime140_1.…

【前后端】HTTP网络传输协议

近期更新完毕&#xff0c;建议关注、收藏&#xff01; http请求 URL 严格意义上应该是URI http or https http不加密不安全&#xff1b;https加密协议&#xff08;公网使用&#xff09; http端口号80 https端口号443GET or POST GET和POST是HTTP请求的两种基本方法. 因为POST需…

多线程 - 自旋锁

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 多线程 - 自旋锁 收录于专栏[Linux学习] 本专栏旨在分享学习Linux的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 概述 原理 优点与…

thinkphp5验证码captcha无法显示

排查思路 是否开启gd2以及gd2排查bom排查代码清除缓存 开启gd/gd2 找到php.ini 开启dg2库 去掉前面的;注释&#xff0c;有的可能会带.dll后缀影响不大 然后通过生成图片验证是否成功 查看是否存在bom 修改为utf-8即可&#xff0c;如果你的代码携带bom也需要排查一下 代码问…

Flutter组件————FloatingActionButton

FloatingActionButton 是Flutter中的一个组件&#xff0c;通常用于显示一个圆形的按钮&#xff0c;它悬浮在内容之上&#xff0c;旨在吸引用户的注意力&#xff0c;并代表屏幕上的主要动作。这种按钮是Material Design的一部分&#xff0c;通常放置在页面的右下角&#xff0c;但…

#{ }和${ } 、参数处理

目录 #{ }和${ } 参数处理 入参-parameterType 使用Map 使用Bean / List<Bean> 使用多参数 Param注解&#xff08;命名参数&#xff09; 出参-resultType 返回Map / List<Map> 返回Map<String,Map> 属性名不一致-resultMap结果映射 #{ }和${ }…

MySQL数据库——门诊管理系统数据库数据表

门诊系统数据库his 使用图形化工具或SQL语句在简明门诊管理系统数据库his中创建数据表&#xff0c;数据表结构见表2-3-9&#xff5e;表2-3-15所示。 表2-3-9 department&#xff08;科室信息表&#xff09; 字段名称 数据类型 长度 是否为空 说明 dep_ID int 否 科室…

Gin-vue-admin(4):项目创建前端一级页面和二级页面

目录 创建一级页面创建二级页面 创建一级页面 view目录下新建一个my&#xff0c;Index.vue <template></template><script> export default {name:My, } </script><script setup> import {ref} from vue const myNameref("name") &…

ABAP SQL 取日期+时间最新的一条数据

我们在系统对接的时候&#xff0c;外部系统可能会推送多个数据给到我们。 我们 SAP 系统的表数据中日期和时间是作为主键的&#xff0c;那么如果通过 ABAP SQL 取到最新日期的最新时间呢。 解决方案&#xff1a; 方式 1&#xff1a;SELECT MAX 可以通过两个 SELECT MAX 来取…

【面试 - 遇到的问题】Vue 里 router-view 使用 key + 关闭页面后重新打开页面-获取的数据赋值到旧组件问题(钩子执行顺序)

目录 【1】问题描述【2】问题排查前 - 页面渲染、tag 页签渲染 逻辑梳理页面渲染【借用别人的描述】<router-view :key"key" />1. 不设置key 属性2. 设置 key 属性值为 $route.path/page/1 > /page/2/page?id1 > /page?id2, 3. 设置 key 属性值为 $rou…

应该连续学一个科目,还是多学科切换?

https://www.zhihu.com/question/333420829https://www.zhihu.com/question/333420829

excel 使用vlook up找出两列中不同的内容

当使用 VLOOKUP 函数时&#xff0c;您可以将其用于比较两列的内容。假设您要比较 A 列和 B 列的内容&#xff0c;并将结果显示在 C 列&#xff0c;您可以在 C1 单元格中输入以下公式&#xff1a; 这个公式将在 B 列中的每个单元格中查找是否存在于 A 列中。如果在 A 列中找不到…

2024159读书笔记|《南山册页:齐白石果蔬册鱼虫册》节选

2024159读书笔记|《南山册页&#xff1a;齐白石果蔬册&鱼虫册》节选 1. 《南山册页&#xff1a;齐白石鱼虫册》2. 《南山册页&#xff1a;齐白石果蔬册》 1. 《南山册页&#xff1a;齐白石鱼虫册》 《南山册页&#xff1a;齐白石鱼虫册》南山书画&#xff0c;大家之作&…

【AI驱动的数据结构:包装类的艺术与科学】

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” 文章目录 包装类装箱和拆箱阿里巴巴面试题 包装类 在Java中基本数据类型不是继承来自Object&#xff0c;为了…

Nginx 双向链表 ngx_queue_t

目录 一、基本概述 二、数据结构 三、接口描述与实现 1、相关宏接口 2、ngx_queue_middle 3、ngx_queue_sort 四、使用案例 整理自 nginx 1.9.2 源码 和 《深入理解 Nginx&#xff1a;模块开发与架构解析》 一、基本概述 双向链表的优势是可以快速进行数据插入、删除与…

亚信安全春节14天双倍假期通告

亚信安全14天双倍假期来袭 “网安福利王”再次实至名归 2024年 8773小时&#xff0c;31582680秒 亚信安全一直驰骋于云网安世界 奋战在“安全 数智化”的壮阔征途上 如今&#xff0c;新春的脚步渐近 长达14天的春节长假 能让我们暂且放下忙碌的工作 去除班味&#xff0c…

【时间之外】IT人求职和创业应知【71】-专利费

目录 2025 ICT产业趋势年会召开&#xff0c;2024年度ICT十大新闻重磅揭晓 海纳致远数字科技申请定制化插件驱动的数据分析专利 阿波罗智联取得语音数据的处理方法、装置、设备和存储介质专利 心勿贪&#xff0c;贵知足。 感谢所有打开这个页面的朋友。人生不如意&#xff0…