Reputation: 469
i have hash-table, which i realising with 2d vector
std::vector<std::vector<std::string> > htable;
Also, i've wrote ++, -- and * operators in my myiterator class, which is subclass of my hash-table.
class myiterator{
public:
myiterator();
myiterator(std::vector<std::vector<std::string> >& v, int ii, int jj) :
vec(v), i(ii), j(jj) {}
std::string operator*(){
return vec[i][j];
}
myiterator& operator++(){
if(j==vec[i].size()-1){
int start=0;
while(vec[start].size()==0){
start++;
}
i=start;
j=0;
}
else{
j++;
}
return *this;
}
// myiterator operator++(int); // postfix operator
myiterator& operator--(){
if(j==0){
int end=vec[i].size()-1;
while(vec[end].size()==0){
end--;
}
i=end;
j=vec[end].size()-1;
}
else{
j--;
}
return *this;
} // prefix operator
// myiterator operator--(int); // postfix operator
std::string* operator->();
private:
std::vector<std::vector<std::string> >& vec; // the vector we are iterating over
int i; // the position in the vector (first dimension)
int j; // the position in the vector (second dimension)
};
myiterator begin() {
int start=0;
while(htable[start].size()==0){
start++;
}
return (myiterator(htable, start, 0));
}
myiterator end(){
int end=htable.size()-1;
while(htable[end].size()==0){
end--;
}
return (myiterator(htable, end, htable[end].size()-1));
}
The question is, how must i implement -> operator? And what does he do? I googled it, but i didn't understand. Sorry if my question is nooby and basic. Thanks in advance.
Upvotes: 0
Views: 114
Reputation: 2934
John already answered your question about operator->
. I just wanted to comment on the operator++
and operator--
. I would have made a comment but this will be a bit long :)
Lets start from this:
myiterator& operator++(){
if(j==vec[i].size()-1){
int start=0;
while(vec[start].size()==0){
start++;
}
i=start;
j=0;
}
else{
j++;
}
return *this;
}
You have the line start=0
. This means that every time you get to the end of an inner vector (j==vec[i].size()-1
) you will start looking for the "next" vector from the start - and then probably get right back to the same vector you started from.
This is a relatively small bug (you should just set start=i+1
instead) but notice how you never check whether you're at the end of the outer vector either! Well, you're not supposed to do ++
on an iterator after the end, right? Actually, you ARE supposed to be able to get to 1 cell after the end! So that would be a problem here. You should be checking if i==vec.size()
somewhere.
Finally - other than these two issues the code looks like it'll work - but it's cumbersome. It can be much simpler. How? Well, you have 2 different cases you split to from the beginning - checking if j==vec[i].size()-1
. I see the logic - but try to think of it a bit differently. It is a well used idiom in c++ to go "one after the last element" to signal the end. You'll see in a sec how that's nicer here too. But the idiom - or the "well used" - way to check if you're at the end is j==vec[i].size()
so when I see the size()-1
I immediately see "things can be simpler".
The other thing that tells me this could be simpler is that you have the same test in two different places: testing if there are no more elements in the current inner vector, so you can move to the next one. You do this both in the line
if (j==vec[i].size()-1)
and
while(vec[start].size()==0)
(you check if the current vector is empty, meaning it has no elements left - as it has no elements at all - and hence you move to the next one)
Both these things (checking twice and using size()-1
) tell me this function can be simpler. Here's an example:
myiterator& operator++(){
j++; // First I increase j! Why? Because I want to get to "one after end" if it's the end
while(j==vec[i].size()){ // in "iterator speak" this is equivalent to "(j==i->end())"
i++;
if (i==vec.size()) // in "iterator speak" this is "i==vec.end()"
break;
j=0; // in "iterator speak" this is "j=i->begin()"
}
return *this;
}
This seems much shorter and more elegant, and especially it makes it easy to "see" the inner iterators if you ever choose to change i
and j
to iterators (meaning you won't need to keep the reference vec
! Only i
and j
!)
Try making operator--
this way too, and if you really want a nice exercise to understand iterators - change like I suggested i
and j
to iterators themselves without having a reference vec
at all and see if you can make it work :)
Upvotes: 1
Reputation: 653
Typically application would be to use the operator -> for smart pointer objects which return a pointer to the internal object. see usage
Upvotes: 0
Reputation: 87959
Looks good so far. I would say
std::string* operator->(){
return &vec[i][j];
}
The odd thing about operator-> is that after calling a user defined operator-> the compiler will call operator-> again on whatever is returned. So your operator-> should return the address of the object you want to access.
Upvotes: 2