A list iterator reference - Program output - c++

Given the following algorithm:
#include <iostream>
#include <list>
int main ()
{
std::list<int> mylist = {5,10,15,20};
std::cout << "mylist contains:"<<"\n";
//for (auto it = mylist.begin(); it != mylist.end(); ++it)
auto it = mylist.begin();
while ( it != mylist.end())
{
std::cout << *it;
std::cout << " "<< &it<<std::endl;
it++;
}
std::cout << '\n';
return 0;
}
The output of this program is:
mylist contains:
5 0x7dc9445e5b50
10 0x7dc9445e5b50
15 0x7dc9445e5b50
20 0x7dc9445e5b50
Since we are moving our iterator, why the address doesn't change?
I was excepting a 4 bytes offset of the reference.

Try this instead:
std::cout << " "<< &*it<<std::endl;
Read this for a description of legacy bidirectional iterators.
https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator
It's not incredibly obvious from this documentation but for this iterator and for iterators in general throughout STL the operator *() will return either:
T & operator *();
or
const T & operator *() const; // for const iterators (list iterator in this case).
I hope this is a bit more explanatory than my previous rather terse answer.

Your problem is pretty simple: it is a variable. Right now, you're printing out the address of that variable. You assign different values to that variable, but the variable is stored at the same location in memory for the entirety of its existence, so when you print out its address, you see the same value every time.
What you want to do is print out the value stored in that variable--the address of the object to which the iterator refers. In the case of an iterator, it can be somewhat tricky to do that, because an iterator is an abstraction--by design, you don't really know what it contains.
We can, however, take a fairly solid guess about how an iterator for an std::list is probably implemented. In particular, it's probably something like this:
template <class T>
class iterator {
T *data;
public:
T &operator*() { return *data; }
// ... and many more functions we don't care about for now
};
The important point here is that although it may store different data to produce its result, operator* needs to return a reference to the object to which the iterator refers. So, to get the address that's (at least effectively) stored in the iterator, we can use operator* to get a reference to the object, then & to take the address of that object.
The downside: while this tells you the addresses of the objects the iterator refers to at different times, it doesn't necessarily tell you what the iterator itself really contains. As long as the iterator produces the correct results from the specified operations, the iterator is free to produce them in essentially any way it sees fit (but that said, with an iterator for an std::list, yes, it's probably going to use a pointer).

Related

C++ - Accessing member functions from a map of object pointers, in a seperate class via getter functions

I'm fairly new to C++, I've tried to figure this out on my own but can't quite get there.
I've defined a map of pointers to a group of dynamically allocated objects in one class, with strings as the keys, along with two iterators (begin() and end()), and two getter functions corresponding to each iterator.
class a{
std::map<string, Fruit*> fruitSalad;
std::map<string, Fruit*>::iterator begin = fruitSalad.begin(), end = fruitSalad.end();
std::map<string, Fruit*>::iterator getBeginIter() const;
std::map<string, Fruit*>::iterator getEndIter() const;
};
the objects referenced in the map, and their member functions need to be accessible in a separate driver class. To test my implementation I've been trying to print values from the objects with a for loop, by accessing the iterators via their accessors, as shown in the code below.
#include "a.h"
int main(){
A fruitBowl;
std::map<string, Object*>::iterator iter;
for(iter = fruitBowl.getBeginIter(); iter != fruitBowl.getEndIter(); iter++){
cout << iter.getName() << " " << iter.getQuantity() << endl;
}
}
But I am getting the following error
error: 'std::map<std::basic_string<char>, Fruit*>:: iterator' has no member named getName()
error: 'std::map<std::basic_string<char>, Fruit*>:: iterator' has no member named getQuantity()
I assume I'm doing something wrong with the assignment of the iterators in my driver class, but what exactly am I doing wrong?
First, when you write iter = fruitBowl.getBeginIter();, iter is an iterator. This is a pointer-like object. If you want to access the method of the pointed-to object, you must first dereference it.
Second, the objects contained in the std::map<foo, bar> are std::pairs of foo, bar.
So the usage looks like
for(iter = fruitBowl.getBeginIter(); iter != fruitBowl.getEndIter(); iter++){
auto pFruit = (*iter).second;
cout << (*pFruit).getName() << " "
<< (*pFruit).getQuantity() << endl;
}
The first dereference is to access the value of the key-value pair in the map;
the second one is to access the Fruit referenced by the pointer.
Or, using the syntactic sugar for pointer manipulation:
for(iter = fruitBowl.getBeginIter(); iter != fruitBowl.getEndIter(); iter++){
auto pFruit = iter->second;
cout << pFruit->getName() << " "
<< pFruit->getQuantity() << endl;
}
Thanks for the responses guys, I appreciate your help.
Turns out it was a relatively simple problem and fix as most beginner programming errors are. I misinterpreted Joachim Pileborg's comment earlier in the thread- I was in fact using begin() and end() to start with, although this comment did set me on the right line of thinking.
The problem was that although I initialized the the iterators that I named 'begin' and 'end' with the iterators returned from the iterator funcitons begin() and end(), I was doing so immediately after I defined the map, before it had any values in it- as shown below.
std::map<string, Fruit*> fruitSalad;
std::map<string, Fruit*>::iterator begin = fruitSalad.begin(), end = fruitSalad.end();
So i guess this meant my iterators both pointed to the same memory location, so when I accessed these iterators via the getters in the driver class, the for loop would terminate just as soon as it would begin which is why no values were being printed even after fixing the original errors in my code as pointed out by mookid.
To remedy this I simply initialised the values of the pointers in class a inside the constructor, which is where the values of the map are read in from a file as shown below.
// class a constructor
a(){
... // initialise some other variables
loadFruitValues(); // reads values in from a .txt file to the map
iter1 = fruitSalad.begin();
iter2 = fruitSalad.end();
}
Now when the code runs the iterators returned correctly point to the beginning and end of the map, allowing the for loop to iterate over the contents stored inside the map.
Thanks again for the replies, I'd still be stuck without all of your input. Both answers helped me equally but I think I can only site one as being the one that helped me the most. And my apologies for my original question not being formatted correctly, it's my first post- I'll try to make sure my next ones on point.

How does the pointer of an iterator in C++ change in a loop?

I was playing around with vectors in C++, and I found this problem, I got quite confused...
#include <vector>
#include <cstdio>
using namespace std;
int main()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
for (vector<int>::iterator it = v.begin(); it != v.end(); ++it)
{
printf("At: %p, %i\n", &it, *it);
}
}
And I did ran this program
g++ -Wall soquestion.cpp -o soquestion
./soquestion
The output
At: 0x7fff59c80a98, 1
At: 0x7fff59c80a98, 2
At: 0x7fff59c80a98, 3
But I thought the addresses of the it was incremented each time??
printf("At: %p, %i\n", &*it, *it);
This will show you what I assume you want. The address of the selected object in the vector followed by the value of the selected object in the vector. Like duffymo said, previously you were referencing the actual it object itself instead of what it is pointing to.
I would interpret the first value as the reference to the iterator object in memory, which isn't changing. Once it's instantiated, the object reference is constant.
The second value is the index into the vector, which is incremented. It's a private data member inside the iterator itself that's being incremented, not the iterator object.
I don't believe you're thinking about the iterator object correctly.
The pointer or iterator object, i.e., it stays put as is nicely demonstrated by the output of &it. However, the pointer's or iterator's value get's incremented resulting in referencing the next value in the sequence. That's shown by *it.
If you want to see where the pointer/iterator actually point's to, you'd use &*it. If it is known to be a pointer you could print it directly:
std::cout << "&it=" << &it << " "
"obj=" << &*it << " "
"value=" << *it << "\n";
Incrementing any object (even a pointer) doesn't change the address of that object. If it's a pointer, incrementing it changes the address it points to, but the address of the pointer itself is still the same. For example in this code, the same address (the address of b) is printed twice.
int a;
int* b = &a;
std::cout << &b << std::endl;
++b;
std::cout << &b << std::endl;
An iterator isn't necessarily a pointer though, it's just some object that overloads the necessary operators to act somewhat like a pointer (at least *, ++ and ==, though sometimes others as well). The same thing still applies though, incrementing the object (or any other operation apart from destroying it) will not change the object's address.
iterator address remains fixed in current scope
I think you wanted probably this :
printf("At: %p, %i\n", &*it, *it);

Implementation of operator!= for Iter Class

Based on the implementation of Iter, I have difficulties to understand operator!= and don't understand why it doesn't check _p_vec?
This is the suggested implementation of operator!= that ONLY compares the _pos.
class Iter
{
public:
Iter (const IntVector* p_vec, int pos)
: _pos( pos )
, _p_vec( p_vec )
{ }
// these three methods form the basis of an iterator for use with
// a range-based for loop
bool operator!= (const Iter& other) const
{
return _pos != other._pos;
}
...
...
private:
int _pos;
const IntVector *_p_vec;
};
However, I think the correct way to do this as follows. In other words, we have to compare both _pos and _p_vec.
bool Iter::operator!= (const Iter& other) const
{
return _p_vec != other._p_vec || _pos != other._pos;
}
Question> Whose code is correct?
===Update on how std::vector works on comparison of iterator====
std::vector<int> vecOne { 1, 2, 3};
std::vector<int> vecTwo { 4, 5, 6};
auto iterOne = vecOne.begin();
std::advance(iterOne, 1);
auto iterTwo = vecTwo.begin();
std::advance(iterTwo, 1);
if ( iterOne == iterTwo)
std::cout << "iterOne == iterTwo" << std::endl;
else
std::cout << "iterOne != iterTwo" << std::endl;
Output is : iterOne != iterTwo
However,
std::vector<int> foo;
std::vector<int> bar;
if ( foo.begin() == bar.begin() )
std::cout << "foo.begin() == bar.begin()" << std::endl;
else
std::cout << "foo.begin() != bar.begin()" << std::endl;
Output is : foo.begin() == bar.begin()
GCC (version 4.7.1)
Also comparing the underlying container reference is an improvement to make sure that, for example, the begin() iterators of two different containers compare equal.
However, iterators of different containers are rarely compared (when using STL algorithms, they never will). So this might be considered an optimization. Think of a loop in which you step from begin() to end(), so the only iterators you are comparing are the "current" one and end(), which are of the same container.
Comparing iterators of standard containers (vector, etc.) is considered undefined behavior. Indeed, since they never are compared in (good) code (for example the standard algorithms), it doesn't have to define a behavior for such cases.
So the author of this Iter class might also want to come back to this point and say: "Comparing iterators of different vectors is undefined behavior."
This being said, if you want to ensure that you never compare iterators of different containers, leave out this check and maybe assert it for debug builds (but don't check it in release builds).
A good example where you might want to compare iterators of different containers is for linked lists, where you define the end of the list being a null pointer (or a pointer to a static null item instance). Consider the iterator being a pointer to a linked list item; in this case, the end() iterator is just a null pointer (or points to this null item). It is the same one for all containers, so you can't implement the check in your comparison method in such cases. Maybe this is one of the reasons why such a comparison isn't defined -- it should return "unequal" when comparing end iterators of different lists, but it can't.
As a general rule, users of iterators are not supposed to compare iterators from different containers. In the standard library, doing so is undefined behavior.
So assuming you are only trying to create iterators that are as robust as standard library ones, comparing the container is not required. However, if you have the pointer to container around, then it would be polite to check that the containers match at least in debug, then assert that you shouldn't be making this comparison.
You are free to check it in release as well, but if your iterator using code is also supposed to work with standard containers, then relying on iterators from different containers comparing not equal is not advised.
See comparing iterators from different containers for someone talking about how it is undefined behavior.

Trying to get Vector iterator to iterating in a different order

My question is twofold:
I have a vector of objects and a vector of integers, I want to iterate on my object vector in the order of the integer vector:
meaning if {water,juice,milk,vodka} is my object vector and {1,0,3,2} is my integer vector I wish to have a const iterator for my object vector that will have juice for the first object, water for the second, vodka and last milk.
is there a simple way of doing this?
suppose I have a function returning const iterator (itr) to a unknown (but accessible) vector
meaning, I can use (itr.getvalue()) but i don't have the size of the vector I'm iterating on, is there a way to make a while loop and know the end or the vector by iterator means?
Question 1:
Omitting most of the boilerplate needed for a proper iterator, the following is how it would work:
template<typename Container, typename Iterator>
class index_iterator
{
public:
typedef typename Container::value_type value_type;
index_iterator(Container& c, Iterator iter):
container(c),
iterator(iter)
{
}
value_type& operator*() { return container[*iterator]; }
index_iterator& operator++() { ++iterator; return *this; }
bool operator==(index_iterator const& other)
{
return &container == &other.container && iterator == other.iterator;
}
// ...
private:
Container& container;
Iterator iterator;
};
template<typename C, typename I>
index_iterator<C, I> indexer(C& container, I iter)
{
return index_iterator<C, I>(container, iter);
}
Then you could write e.g.
std::vector<std::string> vs;
std::vector<int> vi
// fill vs and vi
std::copy(indexer(vs, vi.begin()),
indexer(vs, vi.end()),
std::ostream_iterator<std::string>(std::cout, " "));
Question 2:
No, it isn't possible.
1
#include <iostream>
#include <vector>
std::vector<std::string> foods{"water", "juice", "milk", "vodka"};
std::vector<unsigned int> indexes{1,0,3,2};
for (int i : indexes) { // ranged-for; use normal iteration if you must
std::cout << foods[i] << " ";
}
// Output: juice water vodka milk
Live demo
If you really want to wrap this behaviour into a single iterator for foods, this can be done but it gets a bit more complicated.
2
suppose I have a function returning const iterator (itr) to a unknown (but accessible) vector meaning, I can use (itr.getvalue()) but i don't have the size of the vector I'm iterating on, is there a way to make a while loop and know the end or the vector by iterator means?
If you don't have the vector for its size, and you don't have the vector's end iterator then, no, you can't. You can't reliably iterate over anything with just one iterator; you need a pair or a distance.
Others have already covered number 1. For number 2, it basically comes down to a question of what you're willing to call an iterator. It's certainly possible to define a class that will do roughly what you're asking for -- a single object that both represents a current position and has some way of figuring out when it's been incremented as much as possible.
Most people would call that something like a range rather than an iterator though. You'd have to use it somewhat differently from a normal iterator. Most iterators are used by explicitly comparing them to another iterator representing the end of the range. In this case, you'd pass two separate positions when you created the "iterator" (one for the beginning/current position, the other for the end position) and you'd overload operator bool (for the most obvious choice) to indicate whether the current position had been incremented past the end. You'd use it something like: while (*my_iterator++) operator_on(*my_iterator); -- quite a bit different from using a normal iterator.
I wish to have a const iterator for my object vector that will have
juice for the first object
typedef std::vector<Drink> Drinks;
Drinks drinks;
drinks.push_back("water");
drinks.push_back("juice");
drinks.push_back("milk");
drinks.push_back("vodka");
Drinks::const_iterator i = drinks.begin();
const iterator (itr) to a unknown (but accessible) vector
Drinks::const_iterator itr = some_func();
while (itr != drinks.end()) {
doStuff;
++itr;
}

what is the difference between const_iterator and iterator? [duplicate]

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