《STL源码剖析》-- stl_vector.h

c++stl库头文件及其源码 c++中常用模板库头文件及其源代码,例如,,等 立即下载

http://blog.youkuaiyun.com/mdl13412/article/details/6641998

《STL源码剖析》-- stl_vector.h

  1. // Filename:    stl_vector.h  
  2.   
  3. // Comment By:  凝霜  
  4. // E-mail:      mdl2009@vip.qq.com  
  5. // Blog:        http://blog.youkuaiyun.com/mdl13412  
  6.   
  7. /* 
  8.  * 
  9.  * Copyright (c) 1994 
  10.  * Hewlett-Packard Company 
  11.  * 
  12.  * Permission to use, copy, modify, distribute and sell this software 
  13.  * and its documentation for any purpose is hereby granted without fee, 
  14.  * provided that the above copyright notice appear in all copies and 
  15.  * that both that copyright notice and this permission notice appear 
  16.  * in supporting documentation.  Hewlett-Packard Company makes no 
  17.  * representations about the suitability of this software for any 
  18.  * purpose.  It is provided "as is" without express or implied warranty. 
  19.  * 
  20.  * 
  21.  * Copyright (c) 1996 
  22.  * Silicon Graphics Computer Systems, Inc. 
  23.  * 
  24.  * Permission to use, copy, modify, distribute and sell this software 
  25.  * and its documentation for any purpose is hereby granted without fee, 
  26.  * provided that the above copyright notice appear in all copies and 
  27.  * that both that copyright notice and this permission notice appear 
  28.  * in supporting documentation.  Silicon Graphics makes no 
  29.  * representations about the suitability of this software for any 
  30.  * purpose.  It is provided "as is" without express or implied warranty. 
  31.  */  
  32.   
  33. /* NOTE: This is an internal header file, included by other STL headers. 
  34.  *   You should not attempt to use it directly. 
  35.  */  
  36.   
  37. #ifndef __SGI_STL_INTERNAL_VECTOR_H  
  38. #define __SGI_STL_INTERNAL_VECTOR_H  
  39.   
  40. __STL_BEGIN_NAMESPACE  
  41.   
  42. #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)  
  43. #pragma set woff 1174  
  44. #endif  
  45.   
  46.   
  47. ////////////////////////////////////////////////////////////////////////////////  
  48. //  
  49. ////////////////////////////////////////////////////////////////////////////////  
  50.   
  51.   
  52. // 默认allocator为alloc, 其具体使用版本请参照<stl_alloc.h>  
  53. template <class T, class Alloc = alloc>  
  54. class vector  
  55. {  
  56. public:  
  57.   // 标记为'STL标准强制要求'的typedefs用于提供iterator_traits<I>支持  
  58.   typedef T value_type;                         // STL标准强制要求  
  59.   typedef value_type* pointer;                  // STL标准强制要求  
  60.   typedef const value_type* const_pointer;  
  61.   // 由于vector的特性, 一般我们实作的时候都分配给其连续的内存空间,  
  62.   // 所以其迭代器只需要定义成原生指针即可满足需要  
  63.   typedef value_type* iterator;                 // STL标准强制要求  
  64.   typedef const value_type* const_iterator;  
  65.   typedef value_type& reference;                // STL标准强制要求  
  66.   typedef const value_type& const_reference;  
  67.   typedef size_t size_type;  
  68.   typedef ptrdiff_t difference_type;            // STL标准强制要求  
  69.   
  70. #ifdef __STL_CLASS_PARTIAL_SPECIALIZATION  
  71.   typedef reverse_iterator<const_iterator> const_reverse_iterator;  
  72.   typedef reverse_iterator<iterator> reverse_iterator;  
  73. #else /* __STL_CLASS_PARTIAL_SPECIALIZATION */  
  74.   typedef reverse_iterator<const_iterator, value_type, const_reference,  
  75.                            difference_type>  const_reverse_iterator;  
  76.   typedef reverse_iterator<iterator, value_type, reference, difference_type>  
  77.           reverse_iterator;  
  78. #endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */  
  79.   
  80. protected:  
  81.   // 这个提供STL标准的allocator接口  
  82.   typedef simple_alloc<value_type, Alloc> data_allocator;  
  83.   
  84.   iterator start;               // 内存空间起始点  
  85.   iterator finish;              // 当前使用的内存空间结束点  
  86.   iterator end_of_storage;      // 实际分配内存空间的结束点  
  87.   
  88.   void insert_aux(iterator position, const T& x);  
  89.   
  90.   // 释放分配的内存空间  
  91.   void deallocate()  
  92.   {  
  93.     // 由于使用的是data_allocator进行内存空间的分配,  
  94.     // 所以需要同样嗲用data_allocator::deallocate()进行释放  
  95.     // 如果直接释放, 对于data_allocator内部使用内存池的版本  
  96.     // 就会发生错误  
  97.     if (start) data_allocator::deallocate(start, end_of_storage - start);  
  98.   }  
  99.   
  100.   void fill_initialize(size_type n, const T& value)  
  101.   {  
  102.     start = allocate_and_fill(n, value);  
  103.     finish = start + n;                         // 设置当前使用内存空间的结束点  
  104.     // 构造阶段, 此实作不多分配内存,  
  105.     // 所以要设置内存空间结束点和, 已经使用的内存空间结束点相同  
  106.     end_of_storage = finish;  
  107.   }  
  108.   
  109. public:  
  110.   // 获取几种迭代器  
  111.   iterator begin() { return start; }  
  112.   const_iterator begin() const { return start; }  
  113.   iterator end() { return finish; }  
  114.   const_iterator end() const { return finish; }  
  115.   reverse_iterator rbegin() { return reverse_iterator(end()); }  
  116.   const_reverse_iterator rbegin() const {  
  117.     return const_reverse_iterator(end());  
  118.   }  
  119.   reverse_iterator rend() { return reverse_iterator(begin()); }  
  120.   const_reverse_iterator rend() const {  
  121.     return const_reverse_iterator(begin());  
  122.   }  
  123.   
  124.   // 返回当前对象个数  
  125.   size_type size() const { return size_type(end() - begin()); }  
  126.   size_type max_size() const { return size_type(-1) / sizeof(T); }  
  127.   // 返回重新分配内存前最多能存储的对象个数  
  128.   size_type capacity() const { return size_type(end_of_storage - begin()); }  
  129.   bool empty() const { return begin() == end(); }  
  130.   reference operator[](size_type n) { return *(begin() + n); }  
  131.   const_reference operator[](size_type n) const { return *(begin() + n); }  
  132.   
  133.   // 本实作中默认构造出的vector不分配内存空间  
  134.   vector() : start(0), finish(0), end_of_storage(0) {}  
  135.   
  136. ////////////////////////////////////////////////////////////////////////////////  
  137. // 本实作中给定个数和对象, 则只分配所需内存, 不会多分配  
  138. ////////////////////////////////////////////////////////////////////////////////  
  139. //                    vector(size_type n, const T& value)  
  140. //                                   ↓  
  141. //                         fill_initialize(n, value)  
  142. //                                   ↓  
  143. //                        allocate_and_fill(n, value)  
  144. //                                   ↓  
  145. //          data_allocator::allocate(n)          <stl_alloc.h>  
  146. //          uninitialized_fill_n(result, n, x)  <stl_uninitialized.h>  
  147. ////////////////////////////////////////////////////////////////////////////////  
  148.   
  149.   vector(size_type n, const T& value) { fill_initialize(n, value); }  
  150.   vector(int n, const T& value) { fill_initialize(n, value); }  
  151.   vector(long n, const T& value) { fill_initialize(n, value); }  
  152.   
  153.   // 需要对象提供默认构造函数  
  154.   explicit vector(size_type n) { fill_initialize(n, T()); }  
  155.   
  156. ////////////////////////////////////////////////////////////////////////////////  
  157. // 复制构造, 同样不会多分配内存  
  158. ////////////////////////////////////////////////////////////////////////////////  
  159. //                     vector(const vector<T, Alloc>& x)  
  160. //                                   ↓  
  161. //         allocate_and_copy(x.end() - x.begin(), x.begin(), x.end());  
  162. //                                   ↓  
  163. //        data_allocator::allocate(n)              <stl_alloc.h>  
  164. //        uninitialized_copy(first, last, result); <stl_uninitialized.h>  
  165. ////////////////////////////////////////////////////////////////////////////////  
  166.   
  167.   vector(const vector<T, Alloc>& x)  
  168.   {  
  169.     start = allocate_and_copy(x.end() - x.begin(), x.begin(), x.end());  
  170.     finish = start + (x.end() - x.begin());  
  171.     end_of_storage = finish;  
  172.   }  
  173.   
  174. // 复制指定区间的元素, 同样不多分配内存  
  175. #ifdef __STL_MEMBER_TEMPLATES  
  176. ////////////////////////////////////////////////////////////////////////////////  
  177. // 复制一个区间进行构造, 可能会导致多分配内存  
  178. ////////////////////////////////////////////////////////////////////////////////  
  179. //               vector(InputIterator first, InputIterator last)  
  180. //                                   ↓  
  181. //            range_initialize(first, last, iterator_category(first));  
  182. //                                   ↓  
  183. //                     for ( ; first != last; ++first)  
  184. //                         push_back(*first);  
  185. //            由于使用push_back()操作, 可能导致多次重复分配内存,个人感觉应该先  
  186. //            data_allocator::allocate((last - first) * sizeof(T));  
  187. //            然后uninitialized_copy(first, last, result);  
  188. //            这样不会多分配内存, 也不会导致多次重新分配内存问题  
  189. ////////////////////////////////////////////////////////////////////////////////  
  190.   
  191.   template <class InputIterator>  
  192.   vector(InputIterator first, InputIterator last) :  
  193.     start(0), finish(0), end_of_storage(0)  
  194.   {  
  195.     range_initialize(first, last, iterator_category(first));  
  196.   }  
  197. #else /* __STL_MEMBER_TEMPLATES */  
  198.   
  199. ////////////////////////////////////////////////////////////////////////////////  
  200. // 复制一个区间进行构造, 可能会导致多分配内存  
  201. ////////////////////////////////////////////////////////////////////////////////  
  202. //              vector(const_iterator first, const_iterator last)  
  203. //                                   ↓  
  204. //                        distance(first, last, n);  
  205. //                                   ↓  
  206. //                      allocate_and_copy(n, first, last);  
  207. //                                   ↓  
  208. //       data_allocator::allocate(n)               <stl_alloc.h>  
  209. //       uninitialized_copy(first, last, result);  <stl_uninitialized.h>  
  210. ////////////////////////////////////////////////////////////////////////////////  
  211.   
  212.   vector(const_iterator first, const_iterator last) {  
  213.     size_type n = 0;  
  214.     distance(first, last, n);  
  215.     start = allocate_and_copy(n, first, last);  
  216.     finish = start + n;  
  217.     end_of_storage = finish;  
  218.   }  
  219. #endif /* __STL_MEMBER_TEMPLATES */  
  220.   
  221.   ~vector()  
  222.   {  
  223.     // 析构对象  
  224.     destroy(start, finish);  
  225.     // 释放内存  
  226.     deallocate();  
  227.   }  
  228.   
  229.   vector<T, Alloc>& operator=(const vector<T, Alloc>& x);  
  230.   
  231. ////////////////////////////////////////////////////////////////////////////////  
  232. // 预留一定空间, 如果n < capacity(), 并不会减少空间  
  233. ////////////////////////////////////////////////////////////////////////////////  
  234. //                          reserve(size_type n)  
  235. //                                   ↓  
  236. //                   allocate_and_copy(n, start, finish)  
  237. //                   destroy(start, finish);               <stl_construct.h>  
  238. //                   deallocate();  
  239. ////////////////////////////////////////////////////////////////////////////////  
  240.   
  241.   void reserve(size_type n)  
  242.   {  
  243.     if (capacity() < n) {  
  244.       const size_type old_size = size();  
  245.       iterator tmp = allocate_and_copy(n, start, finish);  
  246.       destroy(start, finish);  
  247.       deallocate();  
  248.       start = tmp;  
  249.       finish = tmp + old_size;  
  250.       end_of_storage = start + n;  
  251.     }  
  252.   }  
  253.   
  254.   // 提供访问函数  
  255.   reference front() { return *begin(); }  
  256.   const_reference front() const { return *begin(); }  
  257.   reference back() { return *(end() - 1); }  
  258.   const_reference back() const { return *(end() - 1); }  
  259.   
  260. ////////////////////////////////////////////////////////////////////////////////  
  261. // 向容器尾追加一个元素, 可能导致内存重新分配  
  262. ////////////////////////////////////////////////////////////////////////////////  
  263. //                          push_back(const T& x)  
  264. //                                   |  
  265. //                                   |---------------- 容量已满?  
  266. //                                   |  
  267. //               ----------------------------  
  268. //           No  |                          |  Yes  
  269. //               |                          |  
  270. //               ↓                          ↓  
  271. //      construct(finish, x);       insert_aux(end(), x);  
  272. //      ++finish;                           |  
  273. //                                          |------ 内存不足, 重新分配  
  274. //                                          |       大小为原来的2倍  
  275. //      new_finish = data_allocator::allocate(len);       <stl_alloc.h>  
  276. //      uninitialized_copy(start, position, new_start);   <stl_uninitialized.h>  
  277. //      construct(new_finish, x);                         <stl_construct.h>  
  278. //      ++new_finish;  
  279. //      uninitialized_copy(position, finish, new_finish); <stl_uninitialized.h>  
  280. ////////////////////////////////////////////////////////////////////////////////  
  281.   
  282.   void push_back(const T& x)  
  283.   {  
  284.     // 内存满足条件则直接追加元素, 否则需要重新分配内存空间  
  285.     if (finish != end_of_storage) {  
  286.       construct(finish, x);  
  287.       ++finish;  
  288.     }  
  289.     else  
  290.       insert_aux(end(), x);  
  291.   }  
  292.   
  293.   // 交换两个vector, 实际上是交换内部的状态指针  
  294.   void swap(vector<T, Alloc>& x)  
  295.   {  
  296.     __STD::swap(start, x.start);  
  297.     __STD::swap(finish, x.finish);  
  298.     __STD::swap(end_of_storage, x.end_of_storage);  
  299.   }  
  300.   
  301. ////////////////////////////////////////////////////////////////////////////////  
  302. // 在指定位置插入元素  
  303. ////////////////////////////////////////////////////////////////////////////////  
  304. //                   insert(iterator position, const T& x)  
  305. //                                   |  
  306. //                                   |------------ 容量是否足够 && 是否是end()?  
  307. //                                   |  
  308. //               -------------------------------------------  
  309. //            No |                                         | Yes  
  310. //               |                                         |  
  311. //               ↓                                         ↓  
  312. //    insert_aux(position, x);                  construct(finish, x);  
  313. //               |                              ++finish;  
  314. //               |-------- 容量是否够用?  
  315. //               |  
  316. //        --------------------------------------------------  
  317. //    Yes |                                                | No  
  318. //        |                                                |  
  319. //        ↓                                                |  
  320. // construct(finish, *(finish - 1));                       |  
  321. // ++finish;                                               |  
  322. // T x_copy = x;                                           |  
  323. // copy_backward(position, finish - 2, finish - 1);        |  
  324. // *position = x_copy;                                     |  
  325. //                                                         ↓  
  326. // data_allocator::allocate(len);                       <stl_alloc.h>  
  327. // uninitialized_copy(start, position, new_start);      <stl_uninitialized.h>  
  328. // construct(new_finish, x);                            <stl_construct.h>  
  329. // ++new_finish;  
  330. // uninitialized_copy(position, finish, new_finish);    <stl_uninitialized.h>  
  331. // destroy(begin(), end());                             <stl_construct.h>  
  332. // deallocate();  
  333. ////////////////////////////////////////////////////////////////////////////////  
  334.   
  335.   iterator insert(iterator position, const T& x)  
  336.   {  
  337.     size_type n = position - begin();  
  338.     if (finish != end_of_storage && position == end()) {  
  339.       construct(finish, x);  
  340.       ++finish;  
  341.     }  
  342.     else  
  343.       insert_aux(position, x);  
  344.     return begin() + n;  
  345.   }  
  346.   
  347.   iterator insert(iterator position) { return insert(position, T()); }  
  348.   
  349. #ifdef __STL_MEMBER_TEMPLATES  
  350. ////////////////////////////////////////////////////////////////////////////////  
  351. // 在指定位置插入一个区间  
  352. ////////////////////////////////////////////////////////////////////////////////  
  353. //     insert(iterator position, InputIterator first, InputIterator last)  
  354. //                                   ↓  
  355. //       range_insert(position, first, last, iterator_category(first));  
  356. //                                   ↓  
  357. //                      for ( ; first != last; ++first) {  
  358. //                              pos = insert(pos, *first);  
  359. //                               ++pos;  
  360. //                      }  
  361. ////////////////////////////////////////////////////////////////////////////////  
  362.   
  363.   template <class InputIterator>  
  364.   void insert(iterator position, InputIterator first, InputIterator last)  
  365.   {  
  366.     range_insert(position, first, last, iterator_category(first));  
  367.   }  
  368. #else /* __STL_MEMBER_TEMPLATES */  
  369.   void insert(iterator position,  
  370.               const_iterator first, const_iterator last);  
  371. #endif /* __STL_MEMBER_TEMPLATES */  
  372.   
  373.   void insert (iterator pos, size_type n, const T& x);  
  374.   
  375.   void insert (iterator pos, int n, const T& x)  
  376.   {  
  377.     insert(pos, (size_type) n, x);  
  378.   }  
  379.   
  380.   void insert (iterator pos, long n, const T& x)  
  381.   {  
  382.     insert(pos, (size_type) n, x);  
  383.   }  
  384.   
  385.   void pop_back()  
  386.   {  
  387.     --finish;  
  388.     destroy(finish);  
  389.   }  
  390.   
  391.   iterator erase(iterator position)  
  392.   {  
  393.     if (position + 1 != end())  
  394.       copy(position + 1, finish, position);  
  395.     --finish;  
  396.     destroy(finish);  
  397.     return position;  
  398.   }  
  399.   
  400. ////////////////////////////////////////////////////////////////////////////////  
  401. // 擦除指定区间的元素  
  402. ////////////////////////////////////////////////////////////////////////////////  
  403. //                 erase(iterator first, iterator last)  
  404. //                                   ↓  
  405. //           ---------- copy(last, finish, first);      <stl_algobase.h>  
  406. //           |          destroy(i, finish);             <stl_construct.h>  
  407. //           |  
  408. //           |                                  -------------- copy(...)  
  409. //           |          特化                    |  char *特化   memmove()  
  410. //      ---------------------------------------|  
  411. //      |  泛化                                 |  wchar_t特化  copy(...)  
  412. //      |                                       -------------- memmove()  
  413. //      |  
  414. // 调用__copy_dispatch<InputIterator,OutputIterator>()(first, last, result);  
  415. // 进行__copy(first, last, result, iterator_category(first));派发  
  416. //      |  
  417. //      |  
  418. //      |                       random_access_iterator_tag  
  419. // --------------------------------------------------------------  
  420. // |  input_iterator_tag                                        |  
  421. // |                                                            |  
  422. // ↓                                                            |  
  423. // __copy(..., input_iterator_tag)                              |  
  424. // for ( ; first != last; ++result, ++first)                    |  
  425. //    *result = *first;                                         ↓  
  426. //                         __copy(..., random_access_iterator_tag)  
  427. //                         __copy_d(first, last, result, distance_type(first));  
  428. //                                              |  
  429. //                                              |  
  430. //                                              ↓  
  431. //              for (Distance n = last - first; n > 0; --n, ++result, ++first)  
  432. //                      *result = *first;  
  433. ////////////////////////////////////////////////////////////////////////////////  
  434.   iterator erase(iterator first, iterator last)  
  435.   {  
  436.     iterator i = copy(last, finish, first);  
  437.     // 析构掉需要析构的元素  
  438.     destroy(i, finish);  
  439.     finish = finish - (last - first);  
  440.     return first;  
  441.   }  
  442.   
  443.   // 调整size, 但是并不会重新分配内存空间  
  444.   void resize(size_type new_size, const T& x)  
  445.   {  
  446.     if (new_size < size())  
  447.       erase(begin() + new_size, end());  
  448.     else  
  449.       insert(end(), new_size - size(), x);  
  450.   }  
  451.   void resize(size_type new_size) { resize(new_size, T()); }  
  452.   
  453.   void clear() { erase(begin(), end()); }  
  454.   
  455. protected:  
  456.   // 分配空间, 并且复制对象到分配的空间处  
  457.   iterator allocate_and_fill(size_type n, const T& x)  
  458.   {  
  459.     iterator result = data_allocator::allocate(n);  
  460.     __STL_TRY {  
  461.       uninitialized_fill_n(result, n, x);  
  462.       return result;  
  463.     }  
  464.     __STL_UNWIND(data_allocator::deallocate(result, n));  
  465.   }  
  466.   
  467. // 分配空间并且拷贝一个区间的元素到新分配空间处  
  468. #ifdef __STL_MEMBER_TEMPLATES  
  469.   template <class ForwardIterator>  
  470.   iterator allocate_and_copy(size_type n,  
  471.                              ForwardIterator first, ForwardIterator last)  
  472.   {  
  473.     iterator result = data_allocator::allocate(n);  
  474.     __STL_TRY {  
  475.       uninitialized_copy(first, last, result);  
  476.       return result;  
  477.     }  
  478.     __STL_UNWIND(data_allocator::deallocate(result, n));  
  479.   }  
  480. #else /* __STL_MEMBER_TEMPLATES */  
  481.   iterator allocate_and_copy(size_type n,  
  482.                              const_iterator first, const_iterator last)  
  483.   {  
  484.     iterator result = data_allocator::allocate(n);  
  485.     __STL_TRY {  
  486.       uninitialized_copy(first, last, result);  
  487.       return result;  
  488.     }  
  489.     __STL_UNWIND(data_allocator::deallocate(result, n));  
  490.   }  
  491. #endif /* __STL_MEMBER_TEMPLATES */  
  492.   
  493.   
  494. #ifdef __STL_MEMBER_TEMPLATES  
  495.   // 初始化一个区间, 使用push_back()操作, 可能引发内存多次重新分配  
  496.   // 解决方案见  
  497.   // template <class InputIterator>  
  498.   // vector(InputIterator first, InputIterator last)  
  499.   // 我评注部分  
  500.   template <class InputIterator>  
  501.   void range_initialize(InputIterator first, InputIterator last,  
  502.                         input_iterator_tag)  
  503.   {  
  504.     for ( ; first != last; ++first)  
  505.       push_back(*first);  
  506.   }  
  507.   
  508.   // This function is only called by the constructor.  We have to worry  
  509.   //  about resource leaks, but not about maintaining invariants.  
  510.   template <class ForwardIterator>  
  511.   void range_initialize(ForwardIterator first, ForwardIterator last,  
  512.                         forward_iterator_tag)  
  513.   {  
  514.     size_type n = 0;  
  515.     distance(first, last, n);  
  516.     start = allocate_and_copy(n, first, last);  
  517.     finish = start + n;  
  518.     end_of_storage = finish;  
  519.   }  
  520.   
  521.   template <class InputIterator>  
  522.   void range_insert(iterator pos,  
  523.                     InputIterator first, InputIterator last,  
  524.                     input_iterator_tag);  
  525.   
  526.   template <class ForwardIterator>  
  527.   void range_insert(iterator pos,  
  528.                     ForwardIterator first, ForwardIterator last,  
  529.                     forward_iterator_tag);  
  530.   
  531. #endif /* __STL_MEMBER_TEMPLATES */  
  532. };  
  533.   
  534. ////////////////////////////////////////////////////////////////////////////////  
  535. // vector实现部分  
  536. ////////////////////////////////////////////////////////////////////////////////  
  537.   
  538. template <class T, class Alloc>  
  539. inline bool operator==(const vector<T, Alloc>& x, const vector<T, Alloc>& y)  
  540. {  
  541.   return x.size() == y.size() && equal(x.begin(), x.end(), y.begin());  
  542. }  
  543.   
  544. // 字典序比较  
  545. template <class T, class Alloc>  
  546. inline bool operator<(const vector<T, Alloc>& x, const vector<T, Alloc>& y)  
  547. {  
  548.   return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());  
  549. }  
  550.   
  551. #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER  
  552.   
  553. template <class T, class Alloc>  
  554. inline void swap(vector<T, Alloc>& x, vector<T, Alloc>& y)  
  555. {  
  556.   x.swap(y);  
  557. }  
  558.   
  559. #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */  
  560.   
  561. ////////////////////////////////////////////////////////////////////////////////  
  562. // 重载赋值运算符  
  563. ////////////////////////////////////////////////////////////////////////////////  
  564. //                  operator=(const vector<T, Alloc>& x)  
  565. //                                   |  
  566. //                                   |---------------- 是否是自赋值?  
  567. //                                   ↓  
  568. //              -----------------------------------------  
  569. //        No    |                                       | Yes  
  570. //              |                                       |  
  571. //              ↓                                       |------- 容量判断  
  572. //        return *this;                                 |  
  573. //                                                      ↓  
  574. //      -----------------------------------------------------------------  
  575. //      |x.size() > capacity()          | size() >= x.size()            | other  
  576. //      |                               |                               |  
  577. //      ↓                               ↓                               |  
  578. //  容量不足, 需要重新分配        容量足够, 只需要析构掉多余的对象             |  
  579. //  allocate_and_copy(         copy(x.begin(), x.end(), begin());       |  
  580. //      x.end() - x.begin(),   destroy(i, finish);                      |  
  581. //      x.begin(), x.end());                                            |  
  582. //  destroy(start, finish);                                             |  
  583. //  deallocate();                                                       ↓  
  584. //                     copy(x.begin(), x.begin() + size(), start);  
  585. //                     uninitialized_copy(x.begin() + size(), x.end(), finish);  
  586. ////////////////////////////////////////////////////////////////////////////////  
  587.   
  588. template <class T, class Alloc>  
  589. vector<T, Alloc>& vector<T, Alloc>::operator=(const vector<T, Alloc>& x)  
  590. {  
  591.   if (&x != this) {  
  592.     // 如果x.size() > capacity()那么就需要重新分配内存  
  593.     // 首先分配内存, 并将容器内原来的元素拷贝到新分配内存中  
  594.     // 然后析构原容器中元素, 调整内存状态变量  
  595.     if (x.size() > capacity()) {  
  596.       iterator tmp = allocate_and_copy(x.end() - x.begin(),  
  597.                                        x.begin(), x.end());  
  598.       destroy(start, finish);  
  599.       deallocate();  
  600.       start = tmp;  
  601.       end_of_storage = start + (x.end() - x.begin());  
  602.     }  
  603.     else if (size() >= x.size()) {  
  604.       iterator i = copy(x.begin(), x.end(), begin());  
  605.       destroy(i, finish);  
  606.     }  
  607.     else {  
  608.       copy(x.begin(), x.begin() + size(), start);  
  609.       uninitialized_copy(x.begin() + size(), x.end(), finish);  
  610.     }  
  611.     finish = start + x.size();  
  612.   }  
  613.   return *this;  
  614. }  
  615.   
  616. ////////////////////////////////////////////////////////////////////////////////  
  617. // 提供插入操作  
  618. ////////////////////////////////////////////////////////////////////////////////  
  619. //                 insert_aux(iterator position, const T& x)  
  620. //                                   |  
  621. //                                   |---------------- 容量是否足够?  
  622. //                                   ↓  
  623. //              -----------------------------------------  
  624. //        Yes   |                                       | No  
  625. //              |                                       |  
  626. //              ↓                                       |  
  627. // 从opsition开始, 整体向后移动一个位置                     |  
  628. // construct(finish, *(finish - 1));                    |  
  629. // ++finish;                                            |  
  630. // T x_copy = x;                                        |  
  631. // copy_backward(position, finish - 2, finish - 1);     |  
  632. // *position = x_copy;                                  |  
  633. //                                                      ↓  
  634. //                            data_allocator::allocate(len);  
  635. //                            uninitialized_copy(start, position, new_start);  
  636. //                            construct(new_finish, x);  
  637. //                            ++new_finish;  
  638. //                            uninitialized_copy(position, finish, new_finish);  
  639. //                            destroy(begin(), end());  
  640. //                            deallocate();  
  641. ////////////////////////////////////////////////////////////////////////////////  
  642.   
  643. template <class T, class Alloc>  
  644. void vector<T, Alloc>::insert_aux(iterator position, const T& x)  
  645. {  
  646.   if (finish != end_of_storage) {       // 还有剩余内存  
  647.     construct(finish, *(finish - 1));  
  648.     ++finish;  
  649.     T x_copy = x;  
  650.     copy_backward(position, finish - 2, finish - 1);  
  651.     *position = x_copy;  
  652.   }  
  653.   else {        // 内存不足, 需要重新分配  
  654.     // 本实作中是按原内存2倍进行重新分配  
  655.     const size_type old_size = size();  
  656.     const size_type len = old_size != 0 ? 2 * old_size : 1;  
  657.     iterator new_start = data_allocator::allocate(len);  
  658.     iterator new_finish = new_start;  
  659.     // 将内存重新配置  
  660.     __STL_TRY {  
  661.       new_finish = uninitialized_copy(start, position, new_start);  
  662.       construct(new_finish, x);  
  663.       ++new_finish;  
  664.       new_finish = uninitialized_copy(position, finish, new_finish);  
  665.     }  
  666. // 分配失败则抛出异常  
  667. #       ifdef  __STL_USE_EXCEPTIONS  
  668.     catch(...) {  
  669.       destroy(new_start, new_finish);  
  670.       data_allocator::deallocate(new_start, len);  
  671.       throw;  
  672.     }  
  673. #       endif /* __STL_USE_EXCEPTIONS */  
  674.     // 析构原容器中的对象  
  675.     destroy(begin(), end());  
  676.     // 释放原容器分配的内存  
  677.     deallocate();  
  678.     // 调整内存指针状态  
  679.     start = new_start;  
  680.     finish = new_finish;  
  681.     end_of_storage = new_start + len;  
  682.   }  
  683. }  
  684.   
  685. ////////////////////////////////////////////////////////////////////////////////  
  686. // 在指定位置插入n个元素  
  687. ////////////////////////////////////////////////////////////////////////////////  
  688. //             insert(iterator position, size_type n, const T& x)  
  689. //                                   |  
  690. //                                   |---------------- 插入元素个数是否为0?  
  691. //                                   ↓  
  692. //              -----------------------------------------  
  693. //        No    |                                       | Yes  
  694. //              |                                       |  
  695. //              |                                       ↓  
  696. //              |                                    return;  
  697. //              |----------- 内存是否足够?  
  698. //              |  
  699. //      -------------------------------------------------  
  700. //  Yes |                                               | No  
  701. //      |                                               |  
  702. //      |------ (finish - position) > n?                |  
  703. //      |       分别调整指针                              |  
  704. //      ↓                                               |  
  705. //    ----------------------------                      |  
  706. // No |                          | Yes                  |  
  707. //    |                          |                      |  
  708. //    ↓                          ↓                      |  
  709. // 插入操作, 调整指针           插入操作, 调整指针           |  
  710. //                                                      ↓  
  711. //            data_allocator::allocate(len);  
  712. //            new_finish = uninitialized_copy(start, position, new_start);  
  713. //            new_finish = uninitialized_fill_n(new_finish, n, x);  
  714. //            new_finish = uninitialized_copy(position, finish, new_finish);  
  715. //            destroy(start, finish);  
  716. //            deallocate();  
  717. ////////////////////////////////////////////////////////////////////////////////  
  718.   
  719. template <class T, class Alloc>  
  720. void vector<T, Alloc>::insert(iterator position, size_type n, const T& x)  
  721. {  
  722.   // 如果n为0则不进行任何操作  
  723.   if (n != 0) {  
  724.     if (size_type(end_of_storage - finish) >= n) {      // 剩下的内存够分配  
  725.       T x_copy = x;  
  726.       const size_type elems_after = finish - position;  
  727.       iterator old_finish = finish;  
  728.       if (elems_after > n) {  
  729.         uninitialized_copy(finish - n, finish, finish);  
  730.         finish += n;  
  731.         copy_backward(position, old_finish - n, old_finish);  
  732.         fill(position, position + n, x_copy);  
  733.       }  
  734.       else {  
  735.         uninitialized_fill_n(finish, n - elems_after, x_copy);  
  736.         finish += n - elems_after;  
  737.         uninitialized_copy(position, old_finish, finish);  
  738.         finish += elems_after;  
  739.         fill(position, old_finish, x_copy);  
  740.       }  
  741.     }  
  742.     else {      // 剩下的内存不够分配, 需要重新分配  
  743.       const size_type old_size = size();  
  744.       const size_type len = old_size + max(old_size, n);  
  745.       iterator new_start = data_allocator::allocate(len);  
  746.       iterator new_finish = new_start;  
  747.       __STL_TRY {  
  748.         new_finish = uninitialized_copy(start, position, new_start);  
  749.         new_finish = uninitialized_fill_n(new_finish, n, x);  
  750.         new_finish = uninitialized_copy(position, finish, new_finish);  
  751.       }  
  752. #         ifdef  __STL_USE_EXCEPTIONS  
  753.       catch(...) {  
  754.         destroy(new_start, new_finish);  
  755.         data_allocator::deallocate(new_start, len);  
  756.         throw;  
  757.       }  
  758. #         endif /* __STL_USE_EXCEPTIONS */  
  759.       destroy(start, finish);  
  760.       deallocate();  
  761.       start = new_start;  
  762.       finish = new_finish;  
  763.       end_of_storage = new_start + len;  
  764.     }  
  765.   }  
  766. }  
  767.   
  768. #ifdef __STL_MEMBER_TEMPLATES  
  769.   
  770. // 在指定位置插入指定区间的对象  
  771. template <class T, class Alloc> template <class InputIterator>  
  772. void vector<T, Alloc>::range_insert(iterator pos,  
  773.                                     InputIterator first, InputIterator last,  
  774.                                     input_iterator_tag)  
  775. {  
  776.   for ( ; first != last; ++first) {  
  777.     pos = insert(pos, *first);  
  778.     ++pos;  
  779.   }  
  780. }  
  781.   
  782. template <class T, class Alloc> template <class ForwardIterator>  
  783. void vector<T, Alloc>::range_insert(iterator position,  
  784.                                     ForwardIterator first,  
  785.                                     ForwardIterator last,  
  786.                                     forward_iterator_tag)  
  787. {  
  788.   if (first != last) {  
  789.     size_type n = 0;  
  790.     distance(first, last, n);  
  791.     if (size_type(end_of_storage - finish) >= n) {  
  792.       const size_type elems_after = finish - position;  
  793.       iterator old_finish = finish;  
  794.       if (elems_after > n) {  
  795.         uninitialized_copy(finish - n, finish, finish);  
  796.         finish += n;  
  797.         copy_backward(position, old_finish - n, old_finish);  
  798.         copy(first, last, position);  
  799.       }  
  800.       else {  
  801.         ForwardIterator mid = first;  
  802.         advance(mid, elems_after);  
  803.         uninitialized_copy(mid, last, finish);  
  804.         finish += n - elems_after;  
  805.         uninitialized_copy(position, old_finish, finish);  
  806.         finish += elems_after;  
  807.         copy(first, mid, position);  
  808.       }  
  809.     }  
  810.     else {  
  811.       const size_type old_size = size();  
  812.       const size_type len = old_size + max(old_size, n);  
  813.       iterator new_start = data_allocator::allocate(len);  
  814.       iterator new_finish = new_start;  
  815.       __STL_TRY {  
  816.         new_finish = uninitialized_copy(start, position, new_start);  
  817.         new_finish = uninitialized_copy(first, last, new_finish);  
  818.         new_finish = uninitialized_copy(position, finish, new_finish);  
  819.       }  
  820. #         ifdef __STL_USE_EXCEPTIONS  
  821.       catch(...) {  
  822.         destroy(new_start, new_finish);  
  823.         data_allocator::deallocate(new_start, len);  
  824.         throw;  
  825.       }  
  826. #         endif /* __STL_USE_EXCEPTIONS */  
  827.       destroy(start, finish);  
  828.       deallocate();  
  829.       start = new_start;  
  830.       finish = new_finish;  
  831.       end_of_storage = new_start + len;  
  832.     }  
  833.   }  
  834. }  
  835.   
  836. #else /* __STL_MEMBER_TEMPLATES */  
  837.   
  838. template <class T, class Alloc>  
  839. void vector<T, Alloc>::insert(iterator position,  
  840.                               const_iterator first,  
  841.                               const_iterator last) {  
  842.   if (first != last) {  
  843.     size_type n = 0;  
  844.     distance(first, last, n);  
  845.     if (size_type(end_of_storage - finish) >= n) {  
  846.       const size_type elems_after = finish - position;  
  847.       iterator old_finish = finish;  
  848.       if (elems_after > n) {  
  849.         uninitialized_copy(finish - n, finish, finish);  
  850.         finish += n;  
  851.         copy_backward(position, old_finish - n, old_finish);  
  852.         copy(first, last, position);  
  853.       }  
  854.       else {  
  855.         uninitialized_copy(first + elems_after, last, finish);  
  856.         finish += n - elems_after;  
  857.         uninitialized_copy(position, old_finish, finish);  
  858.         finish += elems_after;  
  859.         copy(first, first + elems_after, position);  
  860.       }  
  861.     }  
  862.     else {  
  863.       const size_type old_size = size();  
  864.       const size_type len = old_size + max(old_size, n);  
  865.       iterator new_start = data_allocator::allocate(len);  
  866.       iterator new_finish = new_start;  
  867.       __STL_TRY {  
  868.         new_finish = uninitialized_copy(start, position, new_start);  
  869.         new_finish = uninitialized_copy(first, last, new_finish);  
  870.         new_finish = uninitialized_copy(position, finish, new_finish);  
  871.       }  
  872. #         ifdef __STL_USE_EXCEPTIONS  
  873.       catch(...) {  
  874.         destroy(new_start, new_finish);  
  875.         data_allocator::deallocate(new_start, len);  
  876.         throw;  
  877.       }  
  878. #         endif /* __STL_USE_EXCEPTIONS */  
  879.       destroy(start, finish);  
  880.       deallocate();  
  881.       start = new_start;  
  882.       finish = new_finish;  
  883.       end_of_storage = new_start + len;  
  884.     }  
  885.   }  
  886. }  
  887.   
  888. #endif /* __STL_MEMBER_TEMPLATES */  
  889.   
  890. #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)  
  891. #pragma reset woff 1174  
  892. #endif  
  893.   
  894. __STL_END_NAMESPACE  
  895.   
  896. #endif /* __SGI_STL_INTERNAL_VECTOR_H */  
  897.   
  898. // Local Variables:  
  899. // mode:C++  
  900. // End:  


C++ STL VECTOR的实现 c++的STL的vector的一个实现。使用了c++11的大部分特性,包含vector的几乎所有功能。仅作学习之用。 立即下载

相关推荐

STL vector使用

STL VECTOR 、迭代器,DEV C++ 编译运行

【C++】STL 模拟实现之 vector

STL 容器 -- vector 的使用细节及其模拟实现。

在平淡的日子里寻找存在的价值 2685

SPSS中的数据分析—信度效度检验【1】

前一段时间跟大家分享了好几篇关于EXCEL方面的数据分析知识,不知道大家都掌握得怎么样了。今天咱们换个口味,给大家讲一下关于SPSS中的数据分析——信度效度检验。 现阶段正处在毕业季阶段,很多同学可能都正在忙着去弄自己的论文和答辩(不知道大家在翟天临上热搜这个事情上有没有做出过一定贡献),很多时候我们在写论文答辩甚至于其他课题研究的时候都会选择用问卷这种形式来收集数据。最后我们只需要针对问卷所取...

小白数据营的博客 6万+

stl_vector.h源码剖析

vector简述<STL源码剖析> vector是动态空间,随着元素的加入,它的内部机制会自行扩充扩建以容纳新元素。因此,vector的运用对于内存的合理利用与运用的灵活性有很大的帮助 vector的实现技术,关键在于其对大小的控制以及重新配置时的数据移动效率。一旦vector有空间满载,此时扩充空间时"配置新空间/数据移动/释还旧空间"的大成本,时间成本很高。 vector实现 template <class T, class Alloc = alloc> // 默认allo

asladfa的博客 820

跨时钟域传输数据——单bit和多bit信号(总结)

总结单bit和多bit信号的跨时钟域传输

qq_42135020的博客 1万+

对称加密和非对称加密,数字签名和证书

在对称加密中,任何人都可以使用公钥进行加密。在数字签名中,任何人都可以使用公钥验证签名。数字签名,其实就是将非对称加密反过来使用。公钥私钥非对称加密发送者加密时使用接收者解密时使用数字签名验证者验证签名时使用签名者生成签名时使用谁持有密钥?只要有需要,任何人都可以持有个人持有既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密。公钥负责加密,私钥负责解密。既然是签名,那肯定是不希望有人冒充我发消息,所以只有我才能签名。私钥负责签名,公钥负责验签。

m0_70432049的博客 1410

STL源码剖析 [容器](一)[stl_vector.h]

第三章讲的是迭代器,迭代器是将数据和算法很好的连接起来,接下来就学学存放数据的容器。 STL的容器可以分为以下几个大类: 一:序列容器, 有vector, list, deque, string. 二 : 关联容器,     有set, multiset, map, mulmap,hash_set,hash_map, hash_multiset, hash_multimap 三: 其他

深藏功与名 952

Python数据分析师必备:OpenClaw开启Pandas清洗脚本自动生成新时代

本文介绍了OpenClaw这一AI智能体框架如何帮助Python数据分析师高效完成数据清洗工作。OpenClaw通过自然语言交互理解用户需求,自动生成Pandas清洗脚本,显著提升了数据清洗效率,降低了技术门槛。文章详细阐述了OpenClaw的工作原理、实战应用步骤及其在电商、金融、医疗等行业中的成功案例。相比传统手动编写脚本方式,OpenClaw能快速生成规范准确的清洗代码,使数据分析师能更专注于业务洞察。该工具为数据驱动决策提供了可靠支持,是数据分析领域的重要创新。

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 230

【C++】vector的模拟实现

对vector内容进行深入讨论,并模拟实现

s_little_monster的博客 1万+

MATLAB使用贝叶斯网络bnt工具箱:使用手册详解

MATLAB使用贝叶斯bnt网络工具箱:使用手册详解

WW、forever的博客 2676

【数据集8】全球人口数据WorldPop详解

全球人口数据WorldPop详解

WW、forever的博客 7882

《STL源码剖析》---stl_vector.h阅读笔记

在STL中,最常用的就是容器,最常用的容器就是vector了。想要了解vector如何动态增长等特性,看一下stl中vector的代码吧!

KangRoger的专栏 4798

路径规划 | 图解粒子群(PSO)算法(附ROS C++仿真)

粒子群算法(PSO)的基本思想是模拟鸟群觅食机制,将鸟类的觅食方向分为自我认知部分和社会部分,个体自主探索群体周围空间的同时,也随着群体的主流方向前进,不断逼近最优目标。本文详解PSO算法基本概念,并给出ROS C++实现加深理解

FRIGIDWINTER的博客 2617

STL源码剖析 容器 stl_vector.h

vector ---------------------------------------------------------------------- 描述: 1.迭代器 vector 维护的是一个连续线性空间,它的迭代器是普通指针, 能满足 RandomAccessIterator 所有必要条件:operator*, operator->,operator++,operator--,operator+, operator-,operator+=,operator-=,operator[] 2.数据

1386

【AI Guide】AI面试攻略只用看这一篇就够了!力争做全网最全的AI面试攻略——大模型(五)Adapter 微调

Adapter 微调(Adapter Fine-tuning)是一种高效的参数高效微调(PEFT)方法。相较于全参数微调(Full Fine-tuning),Adapter 在预训练模型的特定层插入轻量级的可训练模块,而冻结原始模型参数,从而减少计算和存储开销。是缩放因子,控制 Adapter 输出的影响程度。设 Transformer 层的隐藏状态为。为 Adapter 层的可训练参数,为非线性激活函数,如 ReLU。为冻结的预训练模型参数,

AI科研社 185

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

【2014-06-18】C++ STL读书笔记:allocator

《STL源码剖析》读书笔记,深入分析SGI STL的内存分配器(allocator)实现,包括一级配置器(malloc)和二级配置器(内存池)的源码结构和工作原理。

cstriker1407的专栏 93

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

C++STL:熟悉vector的底层实现,部分源码解析,迭代器失效和深层次浅拷贝

vector<bool>是 vector特化出来的类,是针对存储bool值的特化。这个类型单独提供一些接口,因为存bool值其实是用来标记的接下来看源码。看不懂的不用看,只需要抓住主线去看:第一张图是 typedef ,抓住主要几个核心的:结合这两张图,我们就找到了vector底层的三个指针变量,看名字大概就能知道他们的作用,我们猜测这就是核心的成员它的迭代器是原生指针实现的。接下来看它的构造函数:这一块出现了很多 看似学过,但学的不多的函数,上面的几个简单函数还好,主要是中间的构造函数。

m0_74824865的博客 303

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

【C++】透过STL源代码深度剖析vector的底层

✨Blog’s 主页:🌈个人Motto:他强任他强,清风拂山冈!🔥💫欢迎来到我的学习笔记!

白乐天_ξ( ✿>◡❛)的博客 992

STL 源码剖析之动态数组 vector

STL 源码剖析之动态数组 vector0.导语vector 的数据安排以及操作方式,与 array 非常相似。两者的唯一差别在于空间的运用的灵活性,array 是静态的...

Francis的博客 852

【C++】STL——vector 深度剖析 及 模拟实现

深度剖析vector的底层结构及其模拟实现、详解vector的深拷贝问题、迭代器失效问题等。

m0_70980326的博客 1435

STL源码剖析之allocator&vector

STL源码剖析之Allocator&vector 结合以前学习《STL源码剖析》笔记、理解(与当前版本部分实现细节存在差异),针对gcc6.4.1 STL源码(基于cpp11特性)的设计思想、实现细节作了分析。列出了一系列重要函数,对部分重点设计方式、实现细节做了注释。由于个人技术及文档编排水平有限,可能存在各种问题,欢迎指出及交流讨论。后续会基于本人的优化经验,发布出基于STL底层实现的优化。当然也会分享一些使用SGI STL的注意事项。本系列会保持更新。 文章目录1.对象构造/析构 const

qq_41105501的博客 957

STL源码剖析

STL源码剖析——空间配置器 STL源码剖析——Traits编程技术 STL源码剖析——迭代器 STL源码剖析——全局函数 STL源码剖析——序列容器之vector STL源码剖析——list容器的排序算法sort() STL源码剖析——序列容器之list STL源码剖析——序列容器之deque STL源码剖析——容器配接器之stack STL源码剖析——容器配接器之queue STL源码剖析——...

zzxiaozhao的博客 477

【C++初阶:STL —— vector】vector的介绍及使用 | 迭代器失效问题 | vector的深度剖析及模拟实现

相比于 string,vector 的使用更加容易上手的,且它的接口比 string 要少上许多,再加上我们已经学过类似的 string,并且在数据结构篇的顺序表就已经触及过了。vector 在实际中也非常的重要,在实际中我们熟悉常见的接口就可以了。 在 v 【写在前面】 一、vector的介绍及使用 💦 vector的介绍 💦 vector的使用 二、vector的深度剖析及模拟实现 💦 std::vector的核心框架接口的模拟实现 💦 使用memcpy拷贝问题 💦 对bit::vector核

DanceBit的博客 3188
上一篇: 运算符
下一篇: 函数指针及函数指针数组的妙用
linuxheik
博客等级 码龄15年 865粉丝 135原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值