Red Shift
Red Shift

Reputation: 1312

Iterating through a vector of pointers

I'm trying to iterate through a Players hand of cards.

#include <vector>
#include <iostream>

class Card {
  int card_colour, card_type;
public:
  std::string display_card();
};

std::string Card::display_card(){
  std::stringstream s_card_details;
  s_card_details << "Colour: " << card_colour << "\n";
  s_card_details << "Type: " << card_type << "\n";
    
  return s_card_details.str();
}

int main() 
{
  std::vector<Card*>current_cards;
  vector<Card*>::iterator iter;
  for(iter = current_cards.begin(); iter != current_cards.end(); iter++) 
  {
    std::cout << iter->display_card() << std::endl;
  }
}

This line

std::cout << iter->display_card() << std::endl;

currently comes up with the

error: Expression must have pointer-to-class type.

How can I fix this?

Upvotes: 24

Views: 49700

Answers (4)

Rakib
Rakib

Reputation: 7625

De-referencing the iterator by iter-> gives a pointer to an object of type Card, you have to write (*iter)->display_card();

Upvotes: 2

Joky
Joky

Reputation: 1628

You have to dereference the iterator to access the pointer:

#include <vector>
#include <iostream>

class Card {
public:
  std::string display_card();
};


int main() {
  std::vector<Card*>current_cards;
  std::vector<Card*>::iterator iter, end;
  for(iter = current_cards.begin(), end = current_cards.end() ; iter != end; ++iter) {
    std::cout << (*iter)->display_card() << std::endl;
  }
}

Another observation is the iter++ which you should avoid in profit of ++iter (see https://stackoverflow.com/a/24904/2077394). Depending on the container, you may also want to avoid calling end() each iteration.

Upvotes: 5

Nathan Pierson
Nathan Pierson

Reputation: 5565

An alternative to using (*iter)-> is to pre-emptively dereference the iterator with range-based for.

std::vector<Card*> current_cards;
// Code that populates current_cards goes here...

for(auto p_card : current_cards)
{
    std::cout << p_card->display_card() << std::endl;
}

In the above code, p_card is already a Card* pointer instead of a std::vector<Card*>::iterator iterator. To me this is clearer than the version that explicitly dereferences the iterator and then dereferences the pointer, and is certainly more concise. It also means I don't have to worry about operator precedence pitfalls with -> and unary *.

Upvotes: 1

Reto Koradi
Reto Koradi

Reputation: 54592

Try this:

cout << (*iter)->display_card() << endl;

The * operator gives you the item referenced by the iterator, which in your case is a pointer. Then you use the -> to dereference that pointer.

Upvotes: 41

Related Questions