std::reference_wrapper
isn't default constructable. So I can't write any of:
std::vector<std::reference_wrapper<int>> vec(10);
std::array<std::reference_wrapper<int>, 3> arr;
However, and to my surprise, you can invoke the std::vector::reserve
member function of a vector of std::reference_wrapper
objects and effectively change its capacity.
std::vector<std::reference_wrapper<int>> vec;
vec.reserve(10);
Live Demo
How is this possible since std::reference_wrapper
has no default constructor?
reserve() does not change the size of the vector. If new_cap is greater than capacity(), all iterators, including the past-the-end iterator, and all references to the elements are invalidated. Otherwise, no iterators or references are invalidated.
std::reference_wrapper is a class template that wraps a reference in a copyable, assignable object. It is frequently used as a mechanism to store references inside standard containers (like std::vector) which cannot normally hold references.
vector::reserve does allocate memory, so your question about reserving memory without allocating is incorrect. The point is that reserving memory can be done without changing the vectors size. Basically a vector has two sizes, it's size and it's capacity.
reserve
only allocates uninitialized block of memory enough to fit N
units without causing reallocation when pushing N
new elements.
reserve
doesn't build any new elements. Worst case it only moves/copies already created ones.
You can refer to SGI STL implementation
In stl_vector.h:
void reserve(size_type __n) {
if (capacity() < __n) {
const size_type __old_size = size();
iterator __tmp = _M_allocate_and_copy(__n, _M_start, _M_finish);
destroy(_M_start, _M_finish);
_M_deallocate(_M_start, _M_end_of_storage - _M_start);
_M_start = __tmp;
_M_finish = __tmp + __old_size;
_M_end_of_storage = _M_start + __n;
}
}
void resize(size_type __new_size) { resize(__new_size, _Tp()); }
reserve doesn't create new element, however resize does.
vector::reserve(N)
simply pre-allocates storage capacity for N
elements. The vector constructor you are using is the "default fill" constructor - it creates N
default-constructor elements and inserts them into the container.
E.g.
vector<T> v;
v.reserve(N);
assert(0 == v.size());
assert(N >= v.capacity());
vs
vector<T> v(N);
assert(N == v.size());
assert(N >= v.capacity());
Per 23.3.6.3.p2 [vector.capacity] of the C++17 working draft, vector::reserve()
only requires that T
is MoveInsertable
into *this
. The constructor in question is specified in 23.3.6.2.p3 [vector.cons], and requires that T
shall be DefaultInsertable
into *this
.
reference_wrapper<>
is MoveInsertable
but not DefaultInsertable
(it cannot be default constructed, as you mentioned). For the exact definitions of these concepts, see 23.2.1.p15 [containers.requirements.general].
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With