Take the following code:
std::vector a;
a.reserve(65536);
std::vector b(a); //NOTE: b is constructed from a
a.reserve(65536); // no r
Standard says nothing about preserving capacity when you call copy constructor. So you have no any guarantees about it.
But you can do the following trick, which swap a's and b's state, if you need preserving capacity in the copy only:
std::vector<int> a;
a.reserve(65536);
std::vector<int> b(a);
b.swap(a); // now b has a's state
assert(b.capacity() == 65536);
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);
}
Is capacity copied?
In practice, no. I tested it online in Clang and GCC as well as MSVC and none of them copy the capacity.
Will there be a reallocation on the last line?
If the capacity is less than the argument to reserve (i.e. it doesn't get copied) then yes.
Does the standard say anything about this or is it silent?
No definitions for the copy constructor are provided in vector.cons. Instead we have to look at the container.requirements
Xdenotes a container class containing objects of typeT,aandbdenote values of typeX,udenotes an identifier,rdenotes a non-const value of typeX, andrvdenotes a non-const rvalue of typeX.
X u(a)
X u = a;Requires:
TisCopyInsertableintoX(see below).post:
u == a
Now what does it mean for two containers to be equal?
a == b
==is an equivalence relation.equal(a.begin(), a.end(), b.begin(), b.end())
In other words, since it doesn't require capacity to be equal in the comparison, then there's no reason to copy the capacity.
Well, a simple check like the following reveals that the capacity is not copied:
std::vector<int> a;
a.reserve(65536);
cout << "a.capacity is " << a.capacity() << endl; // prints 65536
std::vector<int> b(a); //NOTE: b is constructed from a
cout << "b.capacity is " << b.capacity() << endl; // prints 0
I believe that upon copying vector a to b, the capacity of b is set to the size of a in most compilers; though this is not guaranteed.
No, capacity is not guaranteed to be preserved by a vector copy construction.
You can do that as follows:
vector<int> b;
b.reserve( a.capacity() );
b = a;
Better encapsulated in a function.