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