73

I have a vector of myObjects in global scope. I have a method which uses a std::vector<myObject>::const_iterator to traverse the vector, and doing some comparisons to find a specific element. Once I have found the required element, I want to be able to return a pointer to it (the vector exists in global scope).

If I return &iterator, am I returning the address of the iterator or the address of what the iterator is pointing to?

Do I need to cast the const_iterator back to a myObject, then return the address of that?

idmean
  • 14,540
  • 9
  • 54
  • 83
Krakkos
  • 1,439
  • 3
  • 19
  • 24
  • 2
    I suggest you read this article from Scott Meyers about iterators usage: http://www.ddj.com/cpp/184401406 He gives guidelines about converting const_iterator to iterator, etc. – Luc Touraille Mar 13 '09 at 09:57

9 Answers9

110

Return the address of the thing pointed to by the iterator:

&(*iterator)

Edit: To clear up some confusion:

vector <int> vec;          // a global vector of ints

void f() {
   vec.push_back( 1 );    // add to the global vector
   vector <int>::iterator it = vec.begin();
   * it = 2;              // change what was 1 to 2
   int * p = &(*it);      // get pointer to first element
   * p = 3;               // change what was 2 to 3
}

No need for vectors of pointers or dynamic allocation.

  • 107
    I don't think think it is a good idea to return the pointer to the object stored in the vector. What happens if vector somebody does a push_back() after we obtain the pointer. The vector may resize and the pointer may become invalid, isn't it? – Naveen Mar 13 '09 at 10:17
  • 3
    Exactly the same is true for iterators. –  Mar 13 '09 at 10:35
  • 3
    Yes, that's why I believe the safest way is to return the copy. – Naveen Mar 13 '09 at 10:45
  • 7
    Copying may be expensive and (although presumambly not in this case) what if you want to modify the object in the vector? –  Mar 13 '09 at 10:47
  • In that case, it should have been stored as vector of pointers not the copies. – Naveen Mar 13 '09 at 10:50
  • If copying MyObjects are expensive then std::vector also will suffer if it have to reallocate objects. – Ismael Mar 13 '09 at 12:28
  • If the vector is mostly static then probably it will be safe to return a pointer or an index into the vector. – Ismael Mar 13 '09 at 12:29
  • Without knowing more about the problem, getting the address looks ugly (well not more that working with raw pointers). – Ismael Mar 13 '09 at 12:33
  • Neil, you're wrong. Getting the address of a stack allocated object and returning a pointer to it is dangerous. If you want to change the value inline, the contents of your vector should be pointers. – Aaron Saarela Mar 13 '09 at 15:07
  • @Aaron things stored in a vector are never allocated on the stack. I'm sorry, but you seem to be very confused about this. –  Mar 13 '09 at 15:27
  • Try std::auto_ptr tmp(myFunction(...)) where myFunction returns a pointer to a stack-allocated member of your vector. Just because it 'works' doesn't mean it's right. – Aaron Saarela Mar 13 '09 at 15:39
  • 1
    @Aaron Once again - things in a vector cannot be allocated on the stack. And this is the end of this conversation from my side. Bye. –  Mar 13 '09 at 15:47
  • See my edit below for an example where returning a pointer to a vector element blows up your app at shutdown. – Aaron Saarela Mar 13 '09 at 20:23
  • 18
    Looking for an answer to exactly the same question, i came across this thread and feel that anybody with the same problem should know: A reallocation of the vector _will_ invalidate all references, pointers and iterators. Inserting/Deleting in the middle of the vector, _will_ invalidate all pointers, references and iterators after the affected index. Sources: http://www.sgi.com/tech/stl/Vector.html, http://stackoverflow.com/questions/3329956/do-stl-iterators-guarantee-validity-after-collection-was-changed. A List container could be an alternative in this case. – quaylar Oct 17 '13 at 06:15
  • Passing the element at a start of a range to a function that analyzes that range, in a single-threaded program, will be safe. Further, in my program, scientific data is read from disk at startup, and never again changes, so the array doesn't reallocate, so even multi-thread access would be safe. If I were putting my analysis function in a library to be called in circumstances I cannot predict, I'd make the caller give me a private copy, but that's not happening in my program. If my analysis function took a vector ref, start and end cell#, then it's be vdata[start+x] instead of adata[x]. – Swiss Frank Jun 15 '21 at 15:33
15

Returning &iterator will return the address of the iterator. If you want to return a way of referring to the element return the iterator itself.

Beware that you do not need the vector to be a global in order to return the iterator/pointer, but that operations in the vector can invalidate the iterator. Adding elements to the vector, for example, can move the vector elements to a different position if the new size() is greater than the reserved memory. Deletion of an element before the given item from the vector will make the iterator refer to a different element.

In both cases, depending on the STL implementation it can be hard to debug with just random errors happening each so often.

EDIT after comment: 'yes, I didn't want to return the iterator a) because its const, and b) surely it is only a local, temporary iterator? – Krakkos'

Iterators are not more or less local or temporary than any other variable and they are copyable. You can return it and the compiler will make the copy for you as it will with the pointer.

Now with the const-ness. If the caller wants to perform modifications through the returned element (whether pointer or iterator) then you should use a non-const iterator. (Just remove the 'const_' from the definition of the iterator).

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • yes, I didn't want to return the iterator a) because its const, and b) surely it is only a local, temporary iterator? – Krakkos Mar 13 '09 at 09:12
8

You can use the data function of the vector:

Returns a pointer to the first element in the vector.

If don't want the pointer to the first element, but by index, then you can try, for example:

//the index to the element that you want to receive its pointer:
int i = n; //(n is whatever integer you want)

std::vector<myObject> vec;
myObject* ptr_to_first = vec.data();

//or

std::vector<myObject>* vec;
myObject* ptr_to_first = vec->data();

//then

myObject element = ptr_to_first[i]; //element at index i
myObject* ptr_to_element = &element;
3

It is not a good idea to return iterators. Iterators become invalid when modifications to the vector (inversion\deletion ) happens. Also, the iterator is a local object created on stack and hence returning the address of the same is not at all safe. I'd suggest you to work with myObject rather than vector iterators.

EDIT: If the object is lightweight then its better you return the object itself. Otheriwise return pointers to myObject stored in the vector.

aJ.
  • 34,624
  • 22
  • 86
  • 128
3

As long as your vector remains in global scope you can return:

&(*iterator)

I'll caution you that this is pretty dangerous in general. If your vector is ever moved out of global scope and is destructed, any pointers to myObject become invalid. If you're writing these functions as part of a larger project, returning a non-const pointer could lead someone to delete the return value. This will have undefined, and catastrophic, effects on the application.

I'd rewrite this as:

myObject myFunction(const vector<myObject>& objects)
{
    // find the object in question and return a copy
    return *iterator;
}

If you need to modify the returned myObject, store your values as pointers and allocate them on the heap:

myObject* myFunction(const vector<myObject*>& objects)
{
    return *iterator;
}

That way you have control over when they're destructed.

Something like this will break your app:

g_vector<tmpClass> myVector;

    tmpClass t;
    t.i = 30;
    myVector.push_back(t);

    // my function returns a pointer to a value in myVector
    std::auto_ptr<tmpClass> t2(myFunction());
Aaron Saarela
  • 3,956
  • 1
  • 19
  • 17
  • Using auto_ptr in a pointer to an object stored in a global is like shooting yourself in the foot. I'd agree that it is dangerous to return a pointer to an object whose lifetime can change, but your sample is not realistic either. – Ismael Mar 13 '09 at 23:42
0

Refer to dirkgently's and anon's answers, you can call the front function instead of begin function, so you do not have to write the *, but only the &.

Code Example:

vector<myObject> vec; //You have a vector of your objects
myObject first = vec.front(); //returns reference, not iterator, to the first object in the vector so you had only to write the data type in the generic of your vector, i.e. myObject, and not all the iterator stuff and the vector again and :: of course
myObject* pointer_to_first_object = &first; //* between & and first is not there anymore, first is already the first object, not iterator to it.
0

I'm not sure if returning the address of the thing pointed by the iterator is needed. All you need is the pointer itself. You will see STL's iterator class itself implementing the use of _Ptr for this purpose. So, just do:

return iterator._Ptr;
arviman
  • 5,087
  • 41
  • 48
0

Say, you have the following:

std::vector<myObject>::const_iterator first = vObj.begin();

Then the first object in the vector is: *first. To get the address, use: &(*first).

However, in keeping with the STL design, I'd suggest return an iterator instead if you plan to pass it around later on to STL algorithms.

dirkgently
  • 108,024
  • 16
  • 131
  • 187
  • I want to return a pointer to a myObject in the vector... the implementation of how that pointer is found my change, hence I didn't want to return an iterator. – Krakkos Mar 13 '09 at 09:14
0

You are storing the copies of the myObject in the vector. So I believe the copying the instance of myObject is not a costly operation. Then I think the safest would be return a copy of the myObject from your function.

Naveen
  • 74,600
  • 47
  • 176
  • 233
  • I need to change some of the properties of the returned myObject, so didn't want to make a copy... by using the pointer method, I can edit them directly. – Krakkos Mar 13 '09 at 11:35