How to change a particular element of a C++ STL vector
vector<int> l;
for(int i=1;i<=10;i++){
l.push_back(i);
}
Now, for example, how do I change the 5th element
of the vector to -1
?
I tried l.assign(4, -1);
It is not behaving as expected. None of the other vector methods seem to fit.
I have used vector as I need random access functionality in my code (using l.at(i)
).
Solution 1:
at
and operator[]
both return a reference to the indexed element, so you can simply use:
l.at(4) = -1;
or
l[4] = -1;
Solution 2:
Even though @JamesMcNellis answer is a valid one I would like to explain something about error handling and also the fact that there is another way of doing what you want.
You have four ways of accessing a specific item in a vector:
- Using the
[]
operator - Using the member function
at(...)
- Using an iterator in combination with a given offset
- Using
std::for_each
from thealgorithm
header of the standard C++ library. This is another way which I can recommend (it uses internally an iterator). You can read more about it for example here.
In the following examples I will be using the following vector as a lab rat and explaining the first three methods:
static const int arr[] = {1, 2, 3, 4};
std::vector<int> v(arr, arr+sizeof(arr)/sizeof(arr[0]));
This creates a vector as seen below:
1 2 3 4
First let's look at the []
way of doing things. It works in pretty much the same way as you expect when working with a normal array. You give an index and possibly you access the item you want. I say possibly because the []
operator doesn't check whether the vector actually has that many items. This leads to a silent invalid memory access. Example:
v[10] = 9;
This may or may not lead to an instant crash. Worst case is of course is if it doesn't and you actually get what seems to be a valid value. Similar to arrays this may lead to wasted time in trying to find the reason why for example 1000 lines of code later you get a value of 100
instead of 234
, which is somewhat connected to that very location where you retrieve an item from you vector.
A much better way is to use at(...)
. This will automatically check for out of bounds
behaviour and break throwing an std::out_of_range
. So in the case when we have
v.at(10) = 9;
We will get:
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check: __n (which is 10) >= this->size() (which is 4)
The third way is similar to the []
operator in the sense you can screw things up. A vector just like an array is a sequence of continuous memory blocks containing data of the same type. This means that you can use your starting address by assigning it to an iterator and then just add an offset to this iterator. The offset simply stands for how many items after the first item you want to traverse:
std::vector<int>::iterator it = v.begin(); // First element of your vector
*(it+0) = 9; // offest = 0 basically means accessing v.begin()
// Now we have 9 2 3 4 instead of 1 2 3 4
*(it+1) = -1; // offset = 1 means first item of v plus an additional one
// Now we have 9 -1 3 4 instead of 9 2 3 4
// ...
As you can see we can also do
*(it+10) = 9;
which is again an invalid memory access. This is basically the same as using at(0 + offset)
but without the out of bounds error checking.
I would advice using at(...)
whenever possible not only because it's more readable compared to the iterator access but because of the error checking for invalid index that I have mentioned above for both the iterator with offset combination and the []
operator.
Solution 3:
This should do it:
l[4] = -1