Why does this vector iterator not become invalidated? - c++

I've read a few posts concerning iterator invalidation, and it seems that inserts that require a vector reallocation would invalidate iterators. Also shouldn't erases in the middle of the vector cause an invalidation?
I don't have a clear understanding of this, not sure why using these iterators after resizes and erases from begin, middle, and end doesn't break them:
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(int argc, char** argv) {
vector<int> v;
v.reserve(10);
for (int i = 0; i < 10; i++)
v.push_back(i);
for (auto x = v.begin(); x != v.end(); x++) {
cout << *x << endl;
}
cout << endl << "RESIZE" << endl << endl;
for (int i = 10; i < 20; i++)
v.push_back(i);
for (auto x = v.begin(); x != v.end(); x++) {
cout << *x << endl;
}
cout << endl << "RESIZE 2" << endl << endl;
for (int i = 20; i < 200; i++)
v.push_back(i);
for (auto x = v.begin(); x != v.end(); x++) {
cout << *x << endl;
}
cout << endl << "REMOVES" << endl << endl;
v.erase(v.begin());
v.pop_back();
v.erase(v.begin() + 17);
for (auto x = v.begin(); x != v.end(); x++) {
cout << *x << endl;
}
return 0;
}

Note that calling begin() or end() will always provide a sane iterator
However something like:
std:vector<int> v;
....
std::vector<int>::iterator i=v.begin();
v.erase(i);
std::cout << *i << std::endl; // i iterator was invalidated by erasing it
// trying to access it or increment it is undefined behaviour.
std::cout << *v.begin() << std::endl; // begin() provides always a sane iterator.

In your code, always when iterators are reused, there was no intervening modification of the vector, so no invalidation.
Iterators may be invalidated on resizing and inserting. Erasing only invalidates iterators at or after the erased element.
At least, those are the paraphrased rules for std::vector.

Related

C++ vector data strucure, loop only half of elements

how to loop only half of the elements in C++ vector data structure using auto keyword
vector<string> InputFIle;
void iterateHalf(){
/* iterate only from begin to half of the size */
for (auto w = InputFIle.begin(); w != InputFIle.end(); w++) {
cout << *w << " : found " << endl;
}
}
You need to compute begin and end of your loop, i.e. first and last_exclusive.
#include <vector>
#include <numeric>
#include <iostream>
int main(){
std::vector<int> vec(16);
std::iota(vec.begin(), vec.end(), 0);
size_t first = 3;
size_t last_exclusive = 7;
//loop using indices
for(size_t i = first; i < last_exclusive; i++){
const auto& w = vec[i];
std::cout << w << " ";
}
std::cout << "\n";
//loop using iterators
for(auto iterator = vec.begin() + first; iterator != vec.begin() + last_exclusive; ++iterator){
const auto& w = *iterator;
std::cout << w << " ";
}
std::cout << "\n";
}

iterator a set in array c++

#include <iostream>
#include <unordered_set>
using namespace std;
void arraySet(unordered_set<int> n[]){
for(auto it1 = n->begin(); it1!= n->end(); it1++){
cout << "n[" <<*it1<<"]: ";
// for(auto it = it1->begin(); it!= it1->end(); it++){
// cout << *it <<" ";
// }
cout << endl;
}
}
int main()
{
unordered_set<int> n[3];
n[0].insert(734);
n[0].insert(23);
n[0].insert(634);
n[1].insert(2);
n[1].insert(1);
n[2].insert(1);
arraySet(n);
return 0;
}
Can anyone help me explain how to iterator through this set inside array. I believe an easy way is to convert it to set inside vector.
Size of the array needs to be passed as well to the function for you to be able to iterate through all the sets of the array. With just passing the pointer, size cannot be determined and dereferencing n->begin will iterate through only the first set.
void arraySet(unordered_set<int> n[], int size) {
for (auto i = 0; i < size; i++) {
for (auto it1 = n[i].begin(); it1 != n[i].end(); it1++) {
cout << "n[" << *it1 << "]: ";
// for(auto it = it1->begin(); it!= it1->end(); it++){
// cout << *it <<" ";
// }
cout << endl;
}
}
}
int main()
{
unordered_set<int> n[3];
n[0].insert(734);
n[0].insert(23);
n[0].insert(634);
n[1].insert(2);
n[1].insert(1);
n[2].insert(1);
arraySet(n,3);
return 0;
}
Or you could use std::vector to contain the sets and pass it instead.
std::vector<unordered_set<int>> n(3); // Sets the size to 3 elements
The function definition would be changed to
void arraySet(std::vector<unordered_set<int>>& n) {
for (size_t i = 0; i < n.size(); i++) {
for (auto it1 = n[i].begin(); it1 != n[i].end(); it1++) {
cout << "n[" << *it1 << "]: ";
// for(auto it = it1->begin(); it!= it1->end(); it++){
// cout << *it <<" ";
// }
cout << endl;
}
}
}

Vectors using C++

Everyone I am new to C++ and just moved from C. While studying vectors I came across this:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector <int> g1;
vector <int> :: iterator i;
vector <int> :: reverse_iterator ir;
for (int i = 1; i <= 5; i++)
g1.push_back(i);
cout << "Output of begin and end\t:\t";
for (i = g1.begin(); i != g1.end(); ++i)
cout << *i << '\t';
cout << endl << endl;
cout << "Output of rbegin and rend\t:\t";
for (ir = g1.rbegin(); ir != g1.rend(); ++ir)
cout << '\t' << *ir;
return 0;
}
My question is why here vector <int> :: iterator i; and is there a difference between vector <int> :: iterator i; and int i?
why here vector <int> :: iterator i;
The vector <int> :: iterator i; is created in order to traverse the vector vector <int> g1; (actually it can traverse any vector<int>, but in this case, that's for g1)
is there a difference between vector <int> :: iterator i; and int i?
The scope of vector <int> :: iterator i; is the main function. Inside main, a new scope is created:
for (int i = 1; i <= 5; i++)
g1.push_back(i);
In that scope, i is the int defined in the loop start, but it dies at the end of the loop, and after that i "returns to be" the vector <int> :: iterator i
int main()
{
vector <int> g1;
vector <int> :: iterator i; // i is the iterator
vector <int> :: reverse_iterator ir;
for (int i = 1; i <= 5; i++) // here i the int
g1.push_back(i); // also here
// from here the int i is dead, and i is back to being an iterator
cout << "Output of begin and end\t:\t";
for (i = g1.begin(); i != g1.end(); ++i)
cout << *i << '\t';
cout << endl << endl;
cout << "Output of rbegin and rend\t:\t";
for (ir = g1.rbegin(); ir != g1.rend(); ++ir)
cout << '\t' << *ir;
return 0;
}
There is difference between vanilla C and modern C++ in that the variables declared in for() would have scope and life length of for() loop body. They are ALLOWED to mask variables with same names, declared in upward scopes.
This example pretty much works in same way:
int main()
{
int i = 5, j;
for(int i = 5; i< 10; i++)
j = i;
std::cout << i << " " << j;
return 0;
}
// Output: 5 9
The code in your question is inelegant and contains a bad practice.
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
using namespace std; // never do this in global scope
vector <int> g1(5); // allocating vector of 5 elements
// nothing is wrong with for() but you can do this too, for more complex cases.
generate(g1.begin(), g1.end(), [](){ static int i = 1; return i++; });
cout << "Output of begin and end\t:\t";
// so called range-based for
for (auto value : g1 )
cout << value << '\t';
cout << endl << endl;
cout << "Output of rbegin and rend\t:\t";
// type of ir is deduced. It's not same as C99's auto keyword
for (auto ir = g1.rbegin(); ir != g1.rend(); ++ir)
cout << '\t' << *ir;
return 0;
}
In first for() loop the auto keyword is deduced to type of container's element. Use of this keyword saves from writing long nested typenames and also is very useful in template code, along with typedecl

Inserting list elements to vector, getting additional unwanted values C++

In my C++ script, I want to insert some elements of a list into a vector (from the beginning of list to a specific position "it"), and then try to add the vector at the top of the list and keeping the same order of the vector but I get unwanted additional elements in the vector.
Here is my code:
#include <iostream>
#include <iterator>
#include <vector>
#include <list>
int main() {
std::list<int> mylist;
for (int i = 0; i < 10; i++)
mylist.push_back(i * 10);
for (std::list<int>::iterator i = mylist.begin(); i <= mylist.end(); ++i) {
std::cout << *i << ", ";
}
std::cout << std::endl;
std::advance(it, 6);
std::cout << "The 6th element in mylist is: " << *it << std::endl;
// The vector that will contain mylist elements
std::vector<int> intAdeplacer;
intAdeplacer.insert(intAdeplacer.end(), mylist.begin(), it);
std::cout << std::endl;
std::cout << "Nombre d'éléments dans le vecteur : " << intAdeplacer.size() << std::endl;
std::cout << std::endl;
// see the content of the vector
std::cout << "Le vecteur de deplacement contient : " << std::endl;
for (std::vector<int>::const_iterator i = intAdeplacer.begin();
i <= intAdeplacer.end(); ++i) {
std::cout << *i << ", ";
}
I get this output:
Le vecteur de deplacement contient :
0, 10, 20, 30, 40, 134985,
134985 is not wanted..
// Insert in front of the list the values of the vector and keeping the same order of elements in the vector
for (std::vector<int>::const_iterator i = intAdeplacer.end();
i >= intAdeplacer.begin(); --i) {
mylist.push_front(*i);
}
std::cout << std::endl;
std::cout << std::endl;
std::cout << "nouvelle composition de mylist : " << std::endl;
for (std::list<int>::const_iterator j = mylist.begin(); j != mylist.end();
++j) {
std::cout << *j << ", ";
}
std::cout << std::endl;
std::cout << std::endl;
// erasing the added elements from mylist
std::list<int>::iterator debut = mylist.begin();
std::list<int>::iterator fin = mylist.end();
std::advance(fin, 6);
mylist.erase(debut, fin);
for (std::list<int>::iterator j = mylist.begin(); j <= mylist.end(); ++j) {
std::cout << *j << ", ";
}
return 0;
}
If it is an iterator pointing at the 6th element of your list, the following insert() will insert from begin() (included) to it (excluded) into the vector:
intAdeplacer.insert(intAdeplacer.end(), mylist.begin(), it);
So you'll have only 5 elements, from 0 to 40. Unfortunately your printing loop does include the end() of the vector, which is out of range. This is why you get this strange trailing number.
Just correct your loop into:
for (auto i = intAdeplacer.begin(); i != intAdeplacer.end(); ++i) {
std::cout << *i << ", ";
}
Or consider this alternate range-for syntax:
for (auto &element: intAdeplacer) {
std::cout << element << ", ";
}

How to print a vector array?

I have a vector array called nVectors.
vector<int>* nVectors[21];
for (int i = 1; i <= 20; i ++) {
nVectors[i] = generateVector(i);
}
I can print all the members of a single vector, but when it comes to the vector array, I still don't know how to print all the vectors in an array.
Maybe an iterator through all the member of a vector array and print using my predefined method pvector can solve this problem? But I don't know how to iterate in gdb.
std::array<std::vector<int>*, 21> nVectors;
for(std::array<std::vector<int>*>::iterator i = nVectors.begin();
i != nVectors.end();
++i)
{
for(std::vector<int>::iterator it = (*i)->begin();
it != (*i)->end();
++it)
{
std::cout << *it << " ";
}
}
std::cout << std::endl;
Or, in C++11:
std::vector<int>* nVectors[21];
for(auto &i : nVectors)
{
for(auto &it : i)
{
std::cout << *it << " ";
}
}
std::cout << std::endl;