I have been told that it is good practice to call vector.reserve()
before inserting a large amount of elements. I just came upon a situation where I want to put a large number of const
elements into a vector
. When calling reserve()
, however, a compiler error is thrown.
Consider the following code reproducing the problem:
#include <vector>
int main()
{
std::vector<const int> vec;
vec.reserve(2);
}
This results in the following huge compiler error:
In file included from /usr/include/x86_64-linux-gnu/c++/4.8/bits/c++allocator.h:33:0, from /usr/include/c++/4.8/bits/allocator.h:46, from /usr/include/c++/4.8/vector:61, from vecreserve.cpp:1: /usr/include/c++/4.8/ext/new_allocator.h: In instantiation of ‘struct __gnu_cxx::new_allocator’: /usr/include/c++/4.8/bits/allocator.h:92:11: required from ‘class std::allocator’ /usr/include/c++/4.8/bits/alloc_traits.h:90:43: required from ‘struct std::allocator_traits >’ /usr/include/c++/4.8/ext/alloc_traits.h:121:10: required from ‘struct __gnu_cxx::__alloc_traits >’ /usr/include/c++/4.8/bits/stl_vector.h:75:28: required from ‘struct std::_Vector_base >’ /usr/include/c++/4.8/bits/stl_vector.h:210:11: required from ‘class std::vector’ vecreserve.cpp:5:26: required from here /usr/include/c++/4.8/ext/new_allocator.h:93:7: error: ‘const _Tp* __gnu_cxx::new_allocator::address(__gnu_cxx::new_allocator::const_reference) const [with _Tp = const int; __gnu_cxx::new_allocator::const_pointer = const int*; __gnu_cxx::new_allocator::const_reference = const int&]’ cannot be overloaded address(const_reference __x) const _GLIBCXX_NOEXCEPT ^ /usr/include/c++/4.8/ext/new_allocator.h:89:7: error: with ‘_Tp* __gnu_cxx::new_allocator::address(__gnu_cxx::new_allocator::reference) const [with _Tp = const int; __gnu_cxx::new_allocator::pointer = const int*; __gnu_cxx::new_allocator::reference = const int&]’ address(reference __x) const _GLIBCXX_NOEXCEPT ^ /usr/include/c++/4.8/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator::deallocate(__gnu_cxx::new_allocator::pointer, __gnu_cxx::new_allocator::size_type) [with _Tp = const int; __gnu_cxx::new_allocator::pointer = const int*; __gnu_cxx::new_allocator::size_type = long unsigned int]’: /usr/include/c++/4.8/bits/stl_vector.h:174:4: required from ‘void std::_Vector_base::_M_deallocate(std::_Vector_base::pointer, std::size_t) [with _Tp = const int; _Alloc = std::allocator; std::_Vector_base::pointer = const int*; std::size_t = long unsigned int]’ /usr/include/c++/4.8/bits/vector.tcc:80:28: required from ‘void std::vector::reserve(std::vector::size_type) [with _Tp = const int; _Alloc = std::allocator; std::vector::size_type = long unsigned int]’ vecreserve.cpp:6:16: required from here /usr/include/c++/4.8/ext/new_allocator.h:110:30: error: invalid conversion from ‘const void*’ to ‘void*’ [-fpermissive] { ::operator delete(__p); } ^ In file included from /usr/include/c++/4.8/ext/new_allocator.h:33:0, from /usr/include/x86_64-linux-gnu/c++/4.8/bits/c++allocator.h:33, from /usr/include/c++/4.8/bits/allocator.h:46, from /usr/include/c++/4.8/vector:61, from vecreserve.cpp:1: /usr/include/c++/4.8/new:95:6: error: initializing argument 1 of ‘void operator delete(void*)’ [-fpermissive] void operator delete(void*) _GLIBCXX_USE_NOEXCEPT ^ In file included from /usr/include/c++/4.8/vector:60:0, from vecreserve.cpp:1: /usr/include/c++/4.8/bits/stl_algobase.h: In instantiation of ‘_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = true; _II = const int*; _OI = const int*]’: /usr/include/c++/4.8/bits/stl_algobase.h:428:38: required from ‘_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = true; _II = const int*; _OI = const int*]’ /usr/include/c++/4.8/bits/stl_algobase.h:460:17: required from ‘_OI std::copy(_II, _II, _OI) [with _II = std::move_iterator; _OI = const int*]’ /usr/include/c++/4.8/bits/stl_uninitialized.h:93:53: required from ‘static _ForwardIterator std::__uninitialized_copy::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator; _ForwardIterator = const int*]’ /usr/include/c++/4.8/bits/stl_uninitialized.h:117:41: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator; _ForwardIterator = const int*]’ /usr/include/c++/4.8/bits/stl_uninitialized.h:258:63: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator&) [with _InputIterator = std::move_iterator; _ForwardIterator = const int*; _Tp = const int]’ /usr/include/c++/4.8/bits/stl_vector.h:1142:29: required from ‘std::vector::pointer std::vector::_M_allocate_and_copy(std::vector::size_type, _ForwardIterator, _ForwardIterator) [with _ForwardIterator = std::move_iterator; _Tp = const int; _Alloc = std::allocator; std::vector::pointer = const int*; std::vector::size_type = long unsigned int]’ /usr/include/c++/4.8/bits/vector.tcc:75:70: required from ‘void std::vector::reserve(std::vector::size_type) [with _Tp = const int; _Alloc = std::allocator; std::vector::size_type = long unsigned int]’ vecreserve.cpp:6:16: required from here /usr/include/c++/4.8/bits/stl_algobase.h:390:70: error: no matching function for call to ‘std::__copy_move::__copy_m(const int*&, const int*&, const int*&)’ _Category>::__copy_m(__first, __last, __result); ^ /usr/include/c++/4.8/bits/stl_algobase.h:390:70: note: candidate is: /usr/include/c++/4.8/bits/stl_algobase.h:368:9: note: template static _Tp* std::__copy_move::__copy_m(const _Tp*, const _Tp*, _Tp*) [with _Tp = _Tp; bool _IsMove = true] __copy_m(const _Tp* __first, const _Tp* __last, _Tp* __result) ^ /usr/include/c++/4.8/bits/stl_algobase.h:368:9: note: template argument deduction/substitution failed: /usr/include/c++/4.8/bits/stl_algobase.h:390:70: note: deduced conflicting types for parameter ‘_Tp’ (‘int’ and ‘const int’) _Category>::__copy_m(__first, __last, __result); ^
Why does this happen? Should I not call reserve
on a vector
of const
elements? If so, why not?
If the allocated memory capacity in the vector is large enough to contain the new elements, no additional allocations for the vector are needed. So no, then it won't reserve memory.
vector<const string>: Cannot change the values of the elements of this vector after they've been added.
You can't put items into a const vector, the vectors state is the items it holds, and adding items to the vector modifies that state. If you want to append to a vector you must take in a non const ref.
vector::reserveIncrease the capacity of the vector (the total number of elements that the vector can hold without requiring reallocation) to a value that's greater or equal to new_cap .
You are violating the requirements for the elements stated by the class vector
. An element must be CopyAssignable.
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