C++ 复制后的向量容量 向量::运算符=是否更改向量容量?如果是,怎么做 vector的复制构造函数是否复制容量

C++ 复制后的向量容量 向量::运算符=是否更改向量容量?如果是,怎么做 vector的复制构造函数是否复制容量,c++,stl,vector,capacity,C++,Stl,Vector,Capacity,我查阅了文档,但没有找到具体的答案。它依赖于实现吗?它依赖于实现。实际上,大多数情况下会将向量缩小到最小大小。您所能保证的是: 向量有足够的容量来存储其元素。(显然。) 向量在当前容量满之前不会获得新容量* 因此,一个实现想要投入多少额外的或很少的东西取决于这个实现。我认为大多数人在复制时会使容量与大小匹配,但不能降低容量。(由于上述第2项原因,不允许在有足够空间时重新分配。) *大部分。参见下面Charles的评论。正如我之前所写,副本不需要——通常也不会——保留原始向量的容量 gcc ver

我查阅了文档,但没有找到具体的答案。它依赖于实现吗?

它依赖于实现。实际上,大多数情况下会将向量缩小到最小大小。

您所能保证的是:

  • 向量有足够的容量来存储其元素。(显然。)
  • 向量在当前容量满之前不会获得新容量*
  • 因此,一个实现想要投入多少额外的或很少的东西取决于这个实现。我认为大多数人在复制时会使容量与大小匹配,但不能降低容量。(由于上述第2项原因,不允许在有足够空间时重新分配。)


    *大部分。参见下面Charles的评论。

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

    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
    
    gcc版本4.1.1 $cat vt.cpp #包括 #包括 int main(){ std::向量v1; v1.储备(50000); 标准:向量v2=v1; 标准::cout vector::operator=是否更改向量容量?如果是,如何更改

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

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

    根据表65 C++03中的容器要求,
    xu(a);
    xu=a;
    都相当于
    xu;u=a;
    。这使得在默认构造向量后,复制向量与op=case相同

  • 正如SGI STL矢量soruce代码如下所示,运算符=将为n元素保留空间,即\u存储的\u M u end\u=\u start+\u xlen;
  • 模板
    载体&
    向量::运算符=(常量向量和x)
    {
    如果(&x!=此){
    const size_type_uuxlen=uuuux.size();
    如果(\uxlen>capacity()){
    迭代器\uuuTMP=\uM\uAllocate\u和\uCopy(\uuxlen,\uuux.begin(),\uuuuux.end());
    销毁(开始、结束);
    _M_解除分配(_M_开始,_M_结束\u存储-_M_开始);
    _M_开始=u tmp;
    _存储器的M_end_=_M_start+_xlen;
    }
    否则如果(大小()>=\uxLen){
    迭代器i=copy(uuux.begin(),uuux.end(),begin());
    销毁(i,M,finish);
    }
    否则{
    复制(uuu x.begin(),uuu x.begin()+大小(),u M_start);
    未初始化的拷贝(uuu x.begin()+size(),uuu x.end(),u M_finish);
    }
    _M_finish=_M_start+_xlen;
    }
    归还*这个;
    }
    
  • 正如SGI STL vector soruce代码如下所示,vector的复制构造函数将为n元素保留空间,即\u存储的\u结束=\u开始+\u n;
  • 模板
    向量(_inputierator uu first,_inputierator u last,
    常量分配器类型(&\u a=allocator\u type()):\u基(\u a){
    typedef typename_是_整数::_Integral_Integral;
    _M_initialize_aux(u first,u last,_Integral());
    }
    模板
    void\u M\u initialize\u aux(\u Integer\u n,\u Integer\u value,\u true\u type){
    _M_开始=_M_分配(u n);
    _存储的M_end_=_M_start+u n;
    _M_finish=未初始化的填充(_M_start,_n,_值);
    }
    
    这似乎是错误的,因为它会使以前的
    reserve()无效。
    @aaa标准只是说“保证在调用reserve()后发生的插入过程中不会发生重新分配。”直到插入会使向量的大小大于最近调用reserve()时指定的大小为止。“.另一个向量的赋值不是插入,因此在赋值过程中可能会发生重新分配,但必须重新分配到相同的,或比先前指定的容量更高的容量(这是有意义的,因为从中分配的向量可能包含更多的元素)。要复制的向量的容量保持不变。复制的向量容量取决于实现,其容量通常会收缩到最小容量。但是,不允许收缩。事实上,这就是为什么
    vector().swap(v)
    习语存在。澄清一下,你是对赋值还是复制构造函数的评论?@litb我的意思是在意义上无效变小。我明白你所说的,没有使用
    运算符=
    @vectros:如果你有
    std::vector v2;v2.reserve(v1.size()*2);v2=v1;
    ,则不允许在复制
    v1
    的内容时收缩其容量。他们编写了
    v2.reserve(size\t)
    ,而不是
    v1。reserve
    @vectros:如果你说litb是对的,我们两个怎么可能都错了?:)而赋值的左侧正是问题所在。复制/赋值的右侧没有什么变化,因为复制构造函数和赋值操作符都有一个
    常量&
    参数。此外,您还陷入了使用特定实现指出语言(及其库)保证的陷阱。特定实现并没有定义语言,而是标准定义了语言。(也就是说,我主要信任gcc。:P)@维克特罗斯:当然,这是问题的一部分。这个问题与容量有关,而储备直接涉及到这一点。事实上,你还不能完全保证(2)当前C++中,保证在调用<代码>保留< /代码>后没有再分配发生,直到插入将超过前一个调用的值,以保留。在调用保留之前,或者在调用前一个调用的预留值和容量执行时调用。如果愿意,允许提前重新分配。这是否可取
        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;
        }
    
          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);
          }