Is there a way to initialize first few elements of a vector after defining the size of the vector like -
vector<int> vec (10);
This doesn't work and produces a compiler error -
vector<int> vec(10) {1,2,3};
For example with arrays we can do the same thing like -
int arr[5] {1,2,3}; // This will initialize the first 3 elements of the array to 1,2,3 and the remaining two to 0.
CodePudding user response:
In short, no. Your can fill out the entire list of things you want to be in the vector:
vector<int> vec{1, 2, 3, 0, 0, 0, 0, 0, 0, 0};
Which will give you a vector
of 10 elements.
Or, you can create the vector
, then call resize
to make it larger (filling the remaining elements with 0
):
vector<int> vec{1, 2, 3};
vec.resize(10);
You generally don't need to do this kind of thing to vector
though, because unlike array
, you can extend vector as needed, after creation:
vector<int> vec{1, 2, 3};
vec.push_back(4);
CodePudding user response:
There isn't a way to do it all in one line like you can with an array. You can use
vector<int> vec{1,2,3};
vec.resize(10);
but that does make the code a little less easy to use. Another option is to wrap that in a function like
template <typename T>
auto make_sized_vector(std::intializer_list<T> il, std::size_t size = 0)
{
const auto vec_size = std::max(size, il.size());
vector<T> vec; // create vector
vec.reserve(vec_size); // allocate all the storage needed
vec.assign(il); // assign the elements
vec.resize(vec_size); // set the rest to zero
return vec;
}
and then you can use that like
auto vec = make_sized_vector<int>({1, 2, 3}, 10);
If you are concerned about passing the std::intializer_list
by value see why is `std::initializer_list` often passed by value? for why that really isn't a concern.
CodePudding user response:
Vector is mutable container, it stores data in the mutable heap area. Whenever you add new elements vector can reallocate heap space. As well as you can free waste heap memory with shrink_to_fit
If you don't need mutable data structure, take a look into std::array
If you just need to initialize from literal you've a few options:
Option one - use assignment from std::initializer_list
std::vector<int> v0 {0,1,2,3};
Option two - assign operator:
std::vector<int> v1 = {0,1,2,3};
Option three - back insertion of initializer_list
std::vector<int> v2( 7 );
v2.insert(v2.end(), {9,8,7});
For example:
#include <iostream>
#include <vector>
template<typename Iterator>
void printv(const Iterator& begin,const Iterator& end) {
Iterator it = begin;
std::cout << "[" << *it;
it;
while(it != end) {
std::cout << ", ";
std::cout << *it;
it;
}
std::cout << "]" << std::endl;
}
int main(int argc, const char** argv) {
std::vector<int> v0 {0,1,2,3,4,5,6,7,8,9};
printv(v0.begin(), v0.end());
std::vector<int> v1 = {0,1,2,3};
printv(v1.begin(), v1.end());
std::vector<int> v2( 7 );
v2.insert(v2.end(), {9,8,7});
printv(v2.begin(), v2.end());
return 0;
}
Gives you:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3]
[0, 0, 0, 0, 0, 0, 0, 9, 8, 7]
CodePudding user response:
In case you want to initialize a vector the way you describe, all at once, so that it can become (e.g.) a const
member, this is always possible in C , with just a bit of ugliness and twisting. Let’s say you have a class:
struct SomeClass {
SomeClass(const std::vector<int> &start, int rest, std::size_t size);
const std::vector<int> some_vector_; // This is const!
};
What the constructor could look like:
SomeClass::SomeClass(const std::vector<int> &start, int rest, std::size_t size)
: some_vector_{[&start, rest, size] {
std::vector<int> some_vector;
some_vector.reserve(size);
some_vector.insert(some_vector.end(), start.begin(), start.end());
some_vector.insert(some_vector.end(), size - start.size(), rest);
return some_vector;
}()} {}
Basically the problem boils down to: How do I do “something procedural” in an initializer list? To which the answer is: You invoke a function that returns the desired type.
To test the construct above:
#include <cstdint>
#include <iostream>
#include <vector>
namespace { /* SomeClass stuff from above goes here. */ }
int main() {
SomeClass sc{{1, 2, 3}, 0, 10};
for (int i : sc.some_vector_) std::cout << i << '\n';
}
There are (of course) plenty of ways to make it (slightly) more efficient if needed, such as
- a templated variadic constructor to create the initial part of the vector,
- a templated perfect-forwarding constructor to benefit from R-value containers, and
- as a combined benefit of the above, arbitrary iterable containers as inputs and as the
const
member.