I get the error:
error C2682: cannot use 'dynamic_cast' to convert from 'std::_List_iterator<_Mylist>' to 'UserBean *'
When executing:
list<UserBean> * userBeans = getUserBeans();
for(list<UserBean>::iterator i = userBeans->begin(); i != userBeans->end(); i++)
UserBean * newUser = dynamic_cast<UserBean*>(i);
Am I doing something wrong, or can you not convert iterator items to objects?
Sometimes iterators are implemented as raw pointers to container items, but more times than not, they are not pointers at all, so don't treat them that way. The correct way to access the item that an iterator refers to is to dereference the iterator, eg:
UserBean &newUser = *i;
Or:
UserBean *newUser = &(*i);
Iterators usually override the -> operator so you can access members of the referenced item, in cases where the iterator refers to an actual object instance (which yours does) and not a pointer to an object instance, eg:
i->SomeMemberHere
Am I doing something wrong, or can you not convert iterator items to objects?
No, you can't. You can dereference iterators to access objects:
UserBean & newUser = *i;
You can't convert an iterator to a pointer like this - that's not what dynamic_cast is for. You should only be using dynamic_cast when you're dealing with polymorphic behaviour (if at all). You can, however, do it like so:
UserBean* newUser = &*i;
This dereferences the iterator to get the object and then takes the address of the object.
The type of your container is list<UserBean> not list<*UserBean>
That's why your iterator is wrong. Its type is UserBean. Not UserBean*.
UserBean userBean = *i;
or
UserBean& userBean = *i;
Related
I need to return a pointer to some value in my list
std::vector<std::list<int>> lists;
...
if(lists.at(i).front()==val){
//return a pointer after the first value
return ptr;
}
The best way i can think of is using std::next, but i have no idea how to make it returns a pointer
The best way i can think of is using std::next, but i have no idea how to make it returns a pointer
std::next returns an iterator. You can use the indirection operator to get the pointed object. You can use the addressof operator to get the memory address (i.e. a pointer) of that object. So:
auto it = whatever; // iterator to the object whose pointer you want
return &*it; // return the pointer
Not relevant to int, but for some rare cases, you may need to use std::addressof in case the the type has an overloaded addressof operator.
Also, I recommend considering whether it makes any sense to return a pointer rather than the iterator itself.
I think of a function like this:
std::list<int>::iterator get(std::vector<std::list<int>>& lists, int i,int val)
{
assert(i<lists.size());
if(lists.at(i).front()==val)
{
//return a pointer after the first value
std::list<int>::iterator it = lists.at(i).begin();
return it++;
}
return lists.at(i).end();
}
Iterators are just "better" pointers. That is, you can use them as pointers (access value by dereferencing them)
auto it = lists.at(i).begin() // returns iterator to first element in i-th list in vector
...
*it // you can access value as if "it" was pointer
it++; // iterators can be "moved", that is, they will point to next element than before
if you really wish to return pointer type *int, instead of std::list<int>::iterator, you dereference it and gain reference back again
return &(*it);
for more on iterators, you can look here. You can see that there are many types of iterators, but all can be dereference as if they were pointers.
std::list<>:iterator is bidirectional iterator (they don't have random access, but you can move them by one element at a time, forward or backward)
I've been trying to understand c++ by going over some projects and i came across this:
vector<Circle>::iterator circleIt = mCircles.end();
..
mCurrentDragCircle = &(*circleIt);
Why would you dereference and then reference it again?
The *-operator is overloaded for the iterator class. It doesn't do a simple dereference. Instead, it returns a reference to the variable it's currently pointing at. Using the reference operator on this returns a pointer towards the variable.
Using mCurrentDragCircle = circleIt; would assign the iterator to your field.
circleIt is an iterator, and iterators overload operator* so that they look like pointers. Dereferencing an iterator gives a reference to the value; & turns that into a pointer to the value. So this is converting an iterator to a pointer.
Btw., dereferencing past-the-end, i.e. *v.end(), has undefined behavior. The proper way to do this is
v.data() + v.size()
in C++11, or
&v[0] + v.size()
in C++98. Both assume the vector is non-empty.
Because of how iterators works.
*circleIt
will return instance of Circle, e.g. you can do
Circle & c = *circleIt;
Than you take address of that circle and store it into a pointer
Circle * mCurrentDragCircle = & (*circleIt);
Hope this helps.
&* is a particularly pernicious idiom for extracting an underlying pointer. It's frequently used on objects that have an overloaded dereference operator *.
One such class of objects are iterators. The author of your class is attempting to get the address of the underlying datum for some reason. (Two pitfalls here, (i) *end() gives undefined behaviour and (ii) it appears that the author is storing the pointer value; blissfully unaware that modifications on that container could invalidate that value).
You can also see it used with smart pointers to circumvent reference counting.
My advice: avoid if at all possible.
What would be the most generic syntax for the following function :
template<IteratorType> void myFunction(const IteratorType& myIterator)
{
_ptr = &myIterator[0];
}
It take an iterator myIterator (it can be a raw pointer) and the goal is to assign the address of the object pointed by myIterator to a raw pointer _ptr. Currently I use &myIterator[0] but I realized that only random access iterators have the operator [].
So is there a syntax that will work with all type of standard iterators and pointers ?
You can dereference pointer and then take address of object.
template<IteratorType> void myFunction(const IteratorType& myIterator)
{
_ptr = &(*myIterator);
}
According to standard * operator return a reference so in my opinion the best way is &*myIterator, but since the class may overloaded the & operator the best way is std::addressof(*myIterator) that work for all classes
All iterators are required to have operator * (24.2.2:2), so you can write
_ptr = &*myIterator;
However, this is not valid for output iterators, where *r is only valid on the left hand side of an assignment operation (24.2.4:2).
Also note that it is not necessarily true that *r will provide a value that & can sensibly be applied to; the specialization std::vector<bool> (23.3.7) has a reference type that is not bool &, for example. In your case the assignment _ptr = &*myIterator would catch this, assuming that _ptr is an appropriate pointer type, and you would get a compile failure.
I hope you guys are all alive right now. If your iterator is an iterator for std::vector, there is a nicer way to get the address that the iterator is holding. You can use:
auto *ptr = myIterator._Ptr;
I hope I could give a proper answer to your question.
If I have a vector of objects (plain objects, not pointers or references), why can't I do this?
Object* object;
object = vectorOfObjects.end();
or
object = &vectorOfObjects.end();
or
object = &(*vectorOfObjects.end());
also the same question if 'object' was a reference.
They are three separate errors:
object = vectorOfObjects.end();
won't work because end() returns a an iterator, and object is a pointer. Those are generally distinct types (A vector can use raw pointers as iterators, but not all implementations do it. Other containers require special iterator types).
object = &vectorOfObjects.end();
doesn't work because you take the address of the returned iterator. That is, you get a pointer to an iterator, rather than a pointer to an Object.
object = &(*vectorOfObjects.end());
doesn't work because the end iterator doesn't point to a valid element. It points one past the end of the sequence. And so, it can't be dereferenced. You can dereference the last element in the sequence (which would be --vectorOfObjects.end()), but not an iterator pointing past the end.
Finally, the underlying problem/confusion might be that you think an iterator can be converted to a pointer. In general, it can't. If your container is a vector, you're guaranteed that elements are allocated contiguously, like in an array, and so a pointer will work. But for, say, a list, a pointer to an element is useless. It doesn't give you any way to reach the next element.
Because .end() returns an iterator, not an Object, which isn't even a valid member of the vector.
Even using begin(), which returns a valid object, you'd need the following:
The correct way would be:
std::vector<Object> vec;
std::vector<Object>::iterator it;
//....
it = vec.begin();
Object o = *it;
This is because by convention end does not point to a valid location in the container: it sits at a location one past the end of the container, so dereferencing it is illegal.
The situation with begin() is different: you can dereference it when v.begin() != v.end() (i.e. when the container is not empty):
object = *vectorOfObjects.begin();
If you need to access the last element, you can do this:
vector<object>::const_iterator i = vectorOfObjects.end();
i--;
cout << *i << endl; // Prints the last element of the container
Again, this works only when your vector contains at least one element.
Object* means a pointer to an Object, where a pointer is a memory address. But the .end() method returns an Iterator, which is an object itself, not a memory address.
I have a vector like so:
vector<MyType*> _types;
And I want to iterate over the vector and call a function on each of MyTypes in the vector, but I'm getting invalid return errors from the compiler. It appears the pos iterator isn't a pointer to MyType, it's something else. What am I not understanding?
Edit: Some code..
for (pos = _types.begin(); pos < _types.end(); pos++)
{
InternalType* inst = *pos->GetInternalType();
}
The compiler errors are:
invalid return type 'InternalType**' for overloaded 'operator ->'
'GetInternalType' : is not a member of 'std::_Vector_iterator<_Ty,_Alloc>'
Edit pt2
Should my vector contain pointers or objects? What are the pros and cons? If I am using new to create an instance, I am guessing I can only use a vector of pointers to MyType is that correct?
If the vector contained objects, not pointers, you could do pos->foo(). The iterator "acts like" a pointer. But your vector contains pointers, so an iterator will act like a pointer to a pointer, so needs to be dereferenced twice.
MyType *pMyType = *pos; // first dereference
if (pMyType) { // make sure the pointer is not null
pMyType->foo(); // second dereference
}
If you are sure the pointer is not null, you could do this:
(*pos)->foo();
The parenthesis around *pos are needed so the dereference applies to pos, not to pos->foo(). Order of operations.
If your vector needs to contain items from a class hierarchy (e.g., subclasses of MyType), then you have to make it a vector of pointers. Otherwise a vector of objects is probably simpler.
You've defined _types as a vector of pointers. Assuming your pos is an iterator into that vector, it's going to be an iterator to a pointer, so you'll need to dereference it twice to get to an instance of MyType.
Edit: based on what you've added to the question: You have something like *pos->whatever. Try (*pos)->whatever instead. As it stands, you're trying to use whatever as a member of the iterator, then dereference the result...
Iterators are not pointers. Iterators are types that behave like pointers. In some implementations of some containers, the iterator type may in fact be a pointer (all pointers are iterators), but this cannot be used as a general rule.
If you need to generate a pointer from an iterator, you can use &*pos, which will dereference the iterator and then get the address of the result (of course, this doesn't work if unary operator & is overloaded, but that's a whole other can of worms).
for (vector<MyType*>::iterator i = _tpes.begin(); i != _types.end(); ++i) {
// do something with i
}
for (vector<MyType*>::iterator it = _types.begin();
it != _types.end();
++it)
{
// `*it` is this iteration's `MyType*` from your vector
}