Archived

This topic is now archived and is closed to further replies.

How to convert pointer to iterator?

This topic is 5012 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Helo How can I properly convert( cast ) pointer to iterator? example:
CObject* pObject;
std::list< CObject >::iterator it;

it = ???? pObject;
I would like to do this:
std::list< CObject >  object;

object.erase( pointer_to_object );

Share this post


Link to post
Share on other sites
The list contains CObjects

You want to remove an object with certain value.

You have a pointer to a CObject

If you dereference the pointer you'll get a CObject

so

objects.remove(*pObject);

edit: sorry, used erase rather than remove. See Jingo below.

[edited by - petewood on March 24, 2004 6:03:22 AM]

Share this post


Link to post
Share on other sites
Helo

Ok, ... I am using STL( standard tamplate library ),
which is standard to C++.

problem:

function:
std::list< >::erase( std::list< >::iterator )

so:

How do I cast from

CObject* pObject to

std::list< CObject >::iterator so that I can do this

object.erase( pointer_to_object )

object is of type std::list< CObject >

Please help!

Share this post


Link to post
Share on other sites

std::list<object_type> list;
...
object_type* pobject = ...
list.remove(*pobject);

//or

list.erase(std::find(list.begin(), list.end(), *pobject));

Share this post


Link to post
Share on other sites
The problem with using either the remove() or find() approach is that both work using the value of the object to be removed. This may not do what is expected. For example if you have a list of ints, with two fives in the list and want to remove the second one based on the pointer. The remove() method will get rid of both elements. The find() method will get rid of the first one, but not the second. This may improperly invalidate pointers.

There are three methods I can think of off the top of my head to actually remove an element by pointer from a std::list. One, std::list::remove_if() with a function object based on address equality. On the other hand, given that address should be unique for all the nodes, a find_if() followed by an erase() may be more efficient. The other method is to explicitly iterate through the list and call erase when finding an iterator of the target address.


template <typename T>
struct address_equals {
address_equals(T * ptr) : ptr_(ptr) {}
bool operator()(int & element) { return &element == ptr_; }
T * ptr_;
};

int main(int, char **) {
int array[] = { 5, 4, 3, 2, 5, 4, 3, 2, 1 };
std::list<int> int_list(array, array + (sizeof(array)/sizeof(int)));
std::list<int>::iterator iter = int_list.begin();
std::advance(iter, 4);
int * ptr = &*iter;

// method 1:

//int_list.remove_if(address_equals<int>(ptr));


// method 2:

//int_list.erase(std::find_if(int_list.begin(), int_list.end(),

// address_equals<int>(ptr)));


// method 3:

for (std::list<int>::iterator i = int_list.begin();
i != int_list.end(); ++i) {
if (&*i == ptr) { int_list.erase(i); break; }
}
std::copy( int_list.begin(), int_list.end(),
std::ostream_iterator<int>(std::cout, ", "));

return 0;
}

Share this post


Link to post
Share on other sites
Helo

Thank you very much SiCrane. That was exactly what I nedeed.
Method II. is the fastest, but still complexity is linear time.
I still have to find the pointer. I was thinking if there is a way
to directy transform pointer to iterator and then call erase. That
would be constant time, right? I need this to be fast as posible
(erasing dead NPCs).

idea: iterator = transform_to_iterator( pointer )

Thanks.





Share this post


Link to post
Share on other sites
The moral of the story is that you really shouldn''t be keeping track of the pointer. Instead, keep track of the iterator. It''ll do almost anything that a pointer will do, and you don''t have to jump through hoops to do something like this.


"Sneftel is correct, if rather vulgar." --Flarelocke

Share this post


Link to post
Share on other sites
There is no 'fast' way to do that. Consider storing iterators instead of pointers in the first place.
Curse you, Sneftel.

[edited by - Beer Hunter on March 26, 2004 2:31:53 AM]

Share this post


Link to post
Share on other sites
Or change data structures. std::vector implementations compliant with the latest standard allow for constant time pointer to iterator conversions.

edit: spelling

[edited by - SiCrane on March 26, 2004 2:46:23 PM]

Share this post


Link to post
Share on other sites