复制后的 std::vector 容量

发布于 2024-08-29 04:20:08 字数 121 浏览 6 评论 0原文

  • vector::operator= 会改变向量容量吗?如果是这样,怎么办?
  • Vector的复制构造函数是否复制容量?

我查看了文档但找不到具体的答案。它依赖于实现吗?

  • Does vector::operator= change vector capacity? If so, how?
  • Does vector's copy constructor copy capacity?

I looked through documentation but could not find a specific answer. Is it implementation dependent?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

昇り龍 2024-09-05 04:20:08

您所保证的是:

  1. 向量有足够的容量来存储其元素。 (显然。)
  2. 向量在其当前容量已满之前不会获得新容量。*

因此,实现想要添加多少额外或少量取决于实现。我认为大多数人在复印时都会使容量与大小匹配,但不能降低容量。 (由于上面的第 2 点;在有足够空间的情况下重新分配是不允许的。)

* 大多数情况下。请参阅下面查尔斯的评论。

All you're guaranteed is that:

  1. The vector has enough capacity to store its elements. (Obviously.)
  2. The vector won't get a new capacity until it's current capacity is full.*

So how much extra or little an implementation wants to put is up to the implementation. I think most will make capacity match size, when copying, but it cannot lower capacity. (Because of number 2 above; reallocating while there's enough room is not allowed.)

* Mostly. See Charles' comments below.

笑梦风尘 2024-09-05 04:20:08

vector::operator= 会改变向量容量吗?如果是这样,怎么办?

它可能会改变容量。仅当先前的容量太小而无法容纳新的大小时,才会发生这种情况。如果是这样,新容量至少等于新大小,但也可以是更大的值。

复制构造函数是否复制容量?

根据表 65 C++03 中的容器要求,X u (a);X u = a; 均等同于 X u; u = a;。在默认构建向量之后,这使得复制向量与 op= 情况相同。

Does vector::operator= change vector capacity? If so, how?

It might change capacity. This happens only if the previous capacity was too small to hold the new size. If so, the new capacity is at least equal to the new size, but could be a larger value.

Does copy constructor copy capacity?

Per Table 65 Container requirements in C++03, X u (a); and X u = a; are both equivalent to X u; u = a;. This makes the copy ctor identical to the op= case, after default constructing the vector.

绝對不後悔。 2024-09-05 04:20:08

正如我之前所写,副本不需要 - 通常也不需要 - 保留原始向量的容量。

gcc version 4.1.1

$ cat vt.cpp
#include <vector>
#include <iostream>
int main() {
   std::vector<int> v1;
   v1.reserve(50000);
   std::vector<int> v2 = v1;
   std::cout << v1.capacity() << std::endl;
   std::cout << v2.capacity() << std::endl;
   return 0;
}

$ g++ vt.cpp -o vt && ./vt
50000
0

$ cat v2.cpp
#include <vector>
#include <iostream>
int main() {
   std::vector<int> v1;
   v1.reserve(50000);
   std::vector<int> v2;
   v2 = v1;
   std::cout << v1.capacity() << std::endl;
   std::cout << v2.capacity() << std::endl;
   return 0;
}

$ g++ v2.cpp -o v2 && ./v2
50000
0

As i wrote before, the copy need not - and usually DOES NOT - retain the capacity of the original vector.

gcc version 4.1.1

$ cat vt.cpp
#include <vector>
#include <iostream>
int main() {
   std::vector<int> v1;
   v1.reserve(50000);
   std::vector<int> v2 = v1;
   std::cout << v1.capacity() << std::endl;
   std::cout << v2.capacity() << std::endl;
   return 0;
}

$ g++ vt.cpp -o vt && ./vt
50000
0

$ cat v2.cpp
#include <vector>
#include <iostream>
int main() {
   std::vector<int> v1;
   v1.reserve(50000);
   std::vector<int> v2;
   v2 = v1;
   std::cout << v1.capacity() << std::endl;
   std::cout << v2.capacity() << std::endl;
   return 0;
}

$ g++ v2.cpp -o v2 && ./v2
50000
0
放血 2024-09-05 04:20:08
  1. 正如下面的 SGI STL 矢量源代码所示,operator= 将为正好 n 个元素保留空间,即 _M_end_of_storage = _M_start + __xlen;
    template <class _Tp, class _Alloc>
    vector<_Tp,_Alloc>&
    vector<_Tp,_Alloc>::operator=(const vector<_Tp, _Alloc>& __x)
    {
      if (&__x != this) {
        const size_type __xlen = __x.size();
        if (__xlen > capacity()) {
          iterator __tmp = _M_allocate_and_copy(__xlen, __x.begin(), __x.end());
          destroy(_M_start, _M_finish);
          _M_deallocate(_M_start, _M_end_of_storage - _M_start);
          _M_start = __tmp;
          _M_end_of_storage = _M_start + __xlen;
        }
        else if (size() >= __xlen) {
          iterator __i = copy(__x.begin(), __x.end(), begin());
          destroy(__i, _M_finish);
        }
        else {
          copy(__x.begin(), __x.begin() + size(), _M_start);
          uninitialized_copy(__x.begin() + size(), __x.end(), _M_finish);
        }
        _M_finish = _M_start + __xlen;
      }
      return *this;
    }
  1. 正如下面的SGI STL向量源代码所示,向量的复制构造函数将为n个元素保留空间,即_M_end_of_storage = _M_start + __n;
      template <class _InputIterator>
      vector(_InputIterator __first, _InputIterator __last,
             const allocator_type& __a = allocator_type()) : _Base(__a) {
        typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
        _M_initialize_aux(__first, __last, _Integral());
      }

      template <class _Integer>
      void _M_initialize_aux(_Integer __n, _Integer __value, __true_type) {
        _M_start = _M_allocate(__n);
        _M_end_of_storage = _M_start + __n;
        _M_finish = uninitialized_fill_n(_M_start, __n, __value);
      }
  1. As SGI STL vector soruce code shows below, operator= will reserve space for exactly n elements, i.e. _M_end_of_storage = _M_start + __xlen;.
    template <class _Tp, class _Alloc>
    vector<_Tp,_Alloc>&
    vector<_Tp,_Alloc>::operator=(const vector<_Tp, _Alloc>& __x)
    {
      if (&__x != this) {
        const size_type __xlen = __x.size();
        if (__xlen > capacity()) {
          iterator __tmp = _M_allocate_and_copy(__xlen, __x.begin(), __x.end());
          destroy(_M_start, _M_finish);
          _M_deallocate(_M_start, _M_end_of_storage - _M_start);
          _M_start = __tmp;
          _M_end_of_storage = _M_start + __xlen;
        }
        else if (size() >= __xlen) {
          iterator __i = copy(__x.begin(), __x.end(), begin());
          destroy(__i, _M_finish);
        }
        else {
          copy(__x.begin(), __x.begin() + size(), _M_start);
          uninitialized_copy(__x.begin() + size(), __x.end(), _M_finish);
        }
        _M_finish = _M_start + __xlen;
      }
      return *this;
    }
  1. As SGI STL vector soruce code shows below, vector's copy constructor will reserve space for exactly n elements, i.e. _M_end_of_storage = _M_start + __n;.
      template <class _InputIterator>
      vector(_InputIterator __first, _InputIterator __last,
             const allocator_type& __a = allocator_type()) : _Base(__a) {
        typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
        _M_initialize_aux(__first, __last, _Integral());
      }

      template <class _Integer>
      void _M_initialize_aux(_Integer __n, _Integer __value, __true_type) {
        _M_start = _M_allocate(__n);
        _M_end_of_storage = _M_start + __n;
        _M_finish = uninitialized_fill_n(_M_start, __n, __value);
      }
难如初 2024-09-05 04:20:08

它取决于实现。大多数实践中将向量缩小到最小尺寸。

It is implementation dependent. Most in practice shrink the vectors to the minimum size.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文