0

I am a beginner as comes to working with iterators and want to iterate through names of my points printing them out. I do not know how to access them, help me out please with an idea. My approach looks like this:

 set<Point::Ptr> points = world->getPoints(); // have set of pointers to Point

 Point::CPtr myPoint = *points.begin(); // dereferenced iterator to the first element
 Point::CPtr lastPoint = *points.rbegin(); //dereferenced iterator to the last valid element

 for(set<Point::Ptr>::iterator it = *points.begin(); it != points.end(); it++) {
    ROS_INFO("points are: %s: ", myPoint.get()->getName().c_str());
 }

Normally for iterator in a loop it shall be set to the first element of the set. But since set contains pointers and I want to be able to call functions available for objects inside those pointers, I tried this way. It works for a one only element like that, giving me desired name:

ROS_INFO("myPoint pointer gives %s: ", myPoint.get()->getName().c_str());

EDIT: typedef boost::shared_ptr CPtr;

beginh
  • 1,133
  • 3
  • 26
  • 36
  • Can you write a loop over a container that doesn't contain pointers? If so, `*it` gives you the element. In your case, all that changes is that this element is a pointer, and I assume you know how to use pointers. There are no exceptions to the general rule for pointers in containers, you need to stop making them up. – Ulrich Eckhardt Feb 08 '16 at 19:11
  • There seems to be some confusion here. Is `CPtr` or `Ptr` actually used? Lines 2 and 3 are irrelevant to the question. – iksemyonov Feb 08 '16 at 21:33

2 Answers2

2

it in the loop below is an iterator. Hence, to access the element that it refers to, you need to dereference it (*it)or use the member access operator (it->).

set<Point::Ptr> points = world->getPoints(); // have set of pointers to Point

for(set<Point::Ptr>::iterator it = points.begin(); it != points.end(); it++) {
   ROS_INFO("points are: %s: ", it->get()->getName().c_str());
   ROS_INFO("points are: %s: ", (*it).get()->getName().c_str());
}

There also is a typo or a deliberate syntax error here:

for(set<Point::Ptr>::iterator it = *points.begin(); it != points.end(); it++) {
//                                ^^^

You want the iterator itself to iterate over the loop, not the value it refers to.

Edit: for OP's and future reference moved here from a comment:

I don't have a reference to Point::Ptr, but it appears to be a pointer class. Thus, to get the Point object that an object of this pointer class stores, you need to call get(). This function returns you a Point* pointer (which is also called a raw pointer) that you can then use like you always use pointers to class objects. In short, this is an example of the common concept of wrapping raw pointers into (more or less) smart pointer classes.

See:

for(set<Point::Ptr>::iterator it = points.begin(); it != points.end(); it++) {
   const Point::Ptr pointer= *it;
   ROS_INFO("points are: %s: ", pointer.get()->getName().c_str());
}

One more edit:

Normally for iterator in a loop it shall be set to the first element of the set.

Wrong. The iterator is set to the iterator pointing to the first element of the set. As @RSahu also pointed out below, you can't assign a container element to an iterator, this is (a) a logical error and (b) a syntax error. And, you may want to begin the iteration from a position other than the collection start, so the "to the first element" part is not quite correct either.

And one more for OP's reference:

What is a smart pointer and when should I use one?

Is it a good practice to always use smart pointers?

When should I use raw pointers over smart pointers?

Community
  • 1
  • 1
iksemyonov
  • 4,106
  • 1
  • 22
  • 42
  • Thanks, the syntax error was my poor try to get into the object methods. Works fine, thanks! What is the function of get() in a loop? that's a main concept which I was missing. – beginh Feb 08 '16 at 19:22
  • Edit: I've moved this explanation into the answer. – iksemyonov Feb 08 '16 at 19:27
  • to recap, `get()` is not related to the actual loop iteration mechanism at all. It's just a method of the class that your container stores. – iksemyonov Feb 08 '16 at 19:36
  • what do you mean by the "collection start"? . begin() returns iterator to the beginning/start from what I understand. – beginh Feb 08 '16 at 20:58
  • also, could you give any reference to the get() usage for pointer class? I google many results for raw pointer (dis)advantages but no clear example. I edit post for Point::Ptr – beginh Feb 08 '16 at 20:59
  • @beginh see my last edit. Collection start is just that, the start of a collection, i.e. its first element. – iksemyonov Feb 08 '16 at 22:29
0

Using

for(set<Point::Ptr>::iterator it = *points.begin(); it != points.end(); it++)

is a problem since it is an iterator, but *points.begin() is not. You need to use:

for(set<Point::Ptr>::iterator it = points.begin(); it != points.end(); it++)
{
   Point::CPtr myPoint = *it;
   // Now you can use myPoint
}

If you are able to use a C++11 compiler, you simplify that with a range-for loop.

for( auto myPoint : points)
{
   // Now you can use myPoint
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270