Help on vector says of front()
Returns a reference to the first element in the vector container.
Unlike member vector::begin, which returns an iterator to this same element, this > function returns a direct reference.
Help on vector says of begin()
Returns an iterator referring to the first element in the vector container.
Notice that unlike member vector::front, which returns a reference to the first element, > this function returns a random access iterator.
And this code outputs:
char arr[] = { 'A', 'B', 'C' };
vector<char> vec(arr, arr+sizeof(arr));
cout << "address of vec.front() " << (void*)&vec.front() << endl;
cout << "address of vec.begin() " << (void*)&vec.begin() << endl;
address of vec.front() 00401F90
address of vec.begin() 0030F494
I don't understand what 'direct reference' means? In the case of begin() isn't a random access iterator just a pointer?
Can someone please point out the difference?
According to Stroustrup in The C++ Programming Language, Section 16.3.3; think of front() as the first element and begin() as a pointer to the first element.
In the case of begin() isn't a random access iterator just a pointer?
No, an iterator has some pointer semantics, but it's actually a class.
And even if it was, that should answer the question. It's like asking why the address of a pointer isn't the same as the address of the object it points to.
You'd get the same value if you dereference the iterator, which will give you the first element:
&(*vec.begin())
because
*vec.begin() == vec.front()
For a vector, begin() and end() return random access iterators. They might return a plain pointer; that's okay, because it meets the requirements to be a random access iterator. In particular, you can write *begin() to get a reference to the first object in the sequence (assuming there is one). front() gives you a reference to the first object in the sequence, without going through the intermediate iterator. Like this:
vector<int> v;
v.push_back(3);
int i = *v.begin(); // i == 3
int j = v.front(); // j == 3
Assuming you have at least 1 element in the vector,
vec.front()
is the same as
*vec.begin()
To keep it clear in your mind, always try to remember the following two lines assuming that you have a vector from STL called v:
v.front() = * v.begin()
&&
v.back() = * v.end()
that means if you have a vector:
v = {1,2,3,4};
and you have an iterator called IT, and you want to access the first and the last element
you can either do:
IT = v.begin();
std::cout<<*IT<<std::endl; // output : 1
IT = v.end();
std::cout<<*IT<<std::endl; // output : 4
or you can easily do this:
std::cout<<v.front<<std::endl; // output : 1
std::cout<<v.back<<std::endl; // output : 4
both will print the same output, the difference is just between if you want to use an iterator or not.
Related
Suppose you have a C++ empty list:
list<int> l;
and you insert three new elements from the beginning:
auto it = l.begin();
l.insert(it,10);
l.insert(it,20);
l.insert(it,30);
when trying to print the list elements from the beginning to the end:
for(int i: l){
cout << i << ' ';
}
the obtained result is: 10 20 30.
But it is supposed that insert function inserts elements before the element pointed by the iterator, so the obtained result should have been: 30 20 10.
Why does this happen?
When the list is empty, the begin() iterator compares equal to the end() iterator. Calling insert() with the end() iterator inserts the value at the end of the list. insert() does not invalidate any iterators, so your it variable is still holding the end() iterator each time you are calling insert().
If you want your values to be in the reverse order that you call insert(), use the iterator that insert() returns to you, eg:
auto it = l.begin();
it = l.insert(it,10);
it = l.insert(it,20);
it = l.insert(it,30);
Live Demo
I want to observe the difference between cbegin and begin.
But when i use cbegin i am getting the same result as begin.
According to definition cbegin will return const itertaor and we cant modify the element using the const iterator returned by cbegin.
But, still i am able to erase the element at particular position.
for (auto i = g1.cbegin(); i != g1.cend(); ++i){
cout << *i << " ";
}
//below code erases element at const pointer
g1.erase(i);
The member function erase accepts const_iterator(s).
For example
iterator erase(const_iterator position);
In early Standards the function indeed was declared with non-constant iterators.
Take into account that the function returns a non-constant iterator but it can be converted implicitly to a constant iterator and can be compared with constant iterators.
By the way this call
g1.erase(i);
erases nothing because after the loop i is equal to the iterator returned by the function cend provided that the name i is defined before the loop.
auto i = g1.cbegin();
for (; i != g1.cend(); ++i){
cout << *i << " ";
}
//below code erases element at const pointer
g1.erase(i);
You can erase an element of the vector using the const_iterator because the vector itself is not constant. If the vector would be constant you could not erase its element.
That is the erase member function changes the vector itself (so it may not be applied to a constant vector), but it does not change elements of the vector using the const_iterator.
Thanks a lot Vlad from Moscow.
I just tried *i=3; in the loop where i am using cend and cbegin.
for (auto it = g1.cbegin(); it != g1.cend(); ++it){
cout << *it << " ";
*it=3;
}
I got compilation error :
error: assignment of read-only location ‘it.__gnu_cxx::__normal_iterator >::operator*()’
*it=3;
^
I am trying to display first element inserted into a vector.Can i use the begin() to access it?
vector<int>s;
s.push_back(5);
cout<<s.begin();
In C++, the begin() member function returns a pointer (or iterator) to the front (a lot of the time, anyways).
You can access the first element with begin(), but you have to dereference it (like a pointer) first:
cout << *s.begin(); // 5
Here is a demo: https://repl.it/JQiU/0
Access with the std::vector::operator[].
vector<int>s;
s.push_back(5);
cout << s[0];
I am trying to access the element of a vector using the iterator. But I get strange outputs.
std::vector<int> ivec{ 7, 6 , 8, 9} ;
std::vector<int>::iterator beg = ivec.begin();
std::vector<int>::iterator last = ivec.end();
std::cout << *beg << *last << std::endl;
But, In the above case the program shows me error: debug assertion failed. Vector iterator not dereferencable. and this error is particularly for *last. If I just print *beg that seems to wrong fine. But can't dereference the last one.
Other problem I get with iterator is during increment.
std::vector<int>::iterator beg = ivec.begin();
cout << *(beg++) ; // in this case it prints me value of 7
cout << *(++beg) ; // in this case it print me the right value of second place i.e. is 6
cout << *(beg+=1) ; // in this case we also print the second value i.e. 6
end iterators are not iterators that you can de-reference. They point past the last element into the container. There's a good reason why this needs to be true; but long and short, the end iterator does not actually point to any element. If you want the last element, you need to decrement the end iterator.
For your first example, std::vector<T>::end points to the theoretical element after the actual last element, so dereferencing it does not make sense. It is primarily used for checking when you have got past the end of the vector in a loop.
For your second example, the results are as you would expect:
cout << *(beg++) ; //increments beg after dereferencing
cout << *(++beg) ; //increments beg before dereferencing
cout << *(beg+=1) ; //dereferences the result of adding one to beg
As it is stated in here,
Return iterator to end, Returns an iterator referring to the past-the-end element in the vector container.
The past-the-end element is the theoretical element that would follow the last element in the vector. It does not point to any element, and thus shall not be dereferenced.
Because the ranges used by functions of the standard library do not include the element pointed by their closing iterator, this function is often used in combination with vector::begin to specify a range including all the elements in the container.
If the container is empty, this function returns the same as vector::begin.
This question already has answers here:
What is the difference between const_iterator and non-const iterator in the C++ STL?
(7 answers)
Closed 4 years ago.
What is difference between these two regarding implementation inside STL.
what is the difference regarding performance?
I guess when we are traversing the vector in "read only wise", we prefer const_iterator, right?
Thank you.
There is no performance difference.
A const_iterator is an iterator that points to const value (like a const T* pointer); dereferencing it returns a reference to a constant value (const T&) and prevents modification of the referenced value: it enforces const-correctness.
When you have a const reference to the container, you can only get a const_iterator.
Edited: I mentionned “The const_iterator returns constant pointers” which is not accurate, thanks to Brandon for pointing it out.
Edit: For COW objects, getting a non-const iterator (or dereferencing it) will probably trigger the copy. (Some obsolete and now disallowed implementations of std::string use COW.)
Performance wise there is no difference. The only purpose of having const_iterator over iterator is to manage the accessesibility of the container on which the respective iterator runs. You can understand it more clearly with an example:
std::vector<int> integers{ 3, 4, 56, 6, 778 };
If we were to read & write the members of a container we will use iterator:
for( std::vector<int>::iterator it = integers.begin() ; it != integers.end() ; ++it )
{*it = 4; std::cout << *it << std::endl; }
If we were to only read the members of the container integers you might wanna use const_iterator which doesn't allow to write or modify members of container.
for( std::vector<int>::const_iterator it = integers.begin() ; it != integers.end() ; ++it )
{ cout << *it << endl; }
NOTE: if you try to modify the content using *it in second case you will get an error because its read-only.
if you have a list a and then following statements
list<int>::iterator it; // declare an iterator
list<int>::const_iterator cit; // declare an const iterator
it=a.begin();
cit=a.begin();
you can change the contents of the element in the list using “it” but not “cit”,
that is you can use “cit” for reading the contents not for updating the elements.
*it=*it+1;//returns no error
*cit=*cit+1;//this will return error