Can I get a ptr to an element from an stl vector iterator?

Discussion in 'C++' started by Steve555, Dec 26, 2008.

  1. Steve555

    Steve555 Guest

    Hi,

    Given a struct:

    struct myStruct{
    int a;
    float b;
    };

    and given a vector containing them, how do I get a ptr to one while
    iterating through that vector:

    myStruct *myStructPtr;
    vector<myStruct>::iterator iter;
    for(iter = myStructVec.begin(); iter != myStructVec.end(); ++ iter)
    {
    myStructPtr = iter; (???
    ChangeStructValuesFunction( myStructPtr );
    ...
    }

    The goal is to modify a & b in-place. I'm doing this in a time-
    critical loop, so I want to do it in place because with very big and
    complicated structs or classes, it seems wasteful to have copy masses
    of data in and out of the vector.

    Thanks

    Steve
    Steve555, Dec 26, 2008
    #1
    1. Advertising

  2. Steve555

    Ian Collins Guest

    Steve555 wrote:
    > Hi,
    >
    > Given a struct:
    >
    > struct myStruct{
    > int a;
    > float b;
    > };
    >
    > and given a vector containing them, how do I get a ptr to one while
    > iterating through that vector:
    >
    > myStruct *myStructPtr;
    > vector<myStruct>::iterator iter;
    > for(iter = myStructVec.begin(); iter != myStructVec.end(); ++ iter)
    > {
    > myStructPtr = iter; (???
    > ChangeStructValuesFunction( myStructPtr );
    > ...
    > }
    >
    > The goal is to modify a & b in-place. I'm doing this in a time-
    > critical loop, so I want to do it in place because with very big and
    > complicated structs or classes, it seems wasteful to have copy masses
    > of data in and out of the vector.
    >

    Why not just use the iterator?

    iter->a = 42;

    --
    Ian Collins
    Ian Collins, Dec 26, 2008
    #2
    1. Advertising

  3. Steve555

    James Kanze Guest

    On Dec 26, 9:26 am, Steve555 <> wrote:
    > Given a struct:


    > struct myStruct{
    > int a;
    > float b;
    > };


    > and given a vector containing them, how do I get a ptr to one
    > while iterating through that vector:


    > myStruct *myStructPtr;
    > vector<myStruct>::iterator iter;
    > for(iter = myStructVec.begin(); iter != myStructVec.end(); ++ iter)
    > {
    > myStructPtr = iter; (???
    > ChangeStructValuesFunction( myStructPtr );
    > ...
    > }


    > The goal is to modify a & b in-place. I'm doing this in a
    > time- critical loop, so I want to do it in place because with
    > very big and complicated structs or classes, it seems wasteful
    > to have copy masses of data in and out of the vector.


    If you're interfacing legacy code to do the modifications,
    &*iter will do the trick, but most of the time, either the
    function should take a reference (so you pass *iter), or you
    will be modifying the fields in place iter->fieldName.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Dec 26, 2008
    #3
  4. Steve555

    Kai-Uwe Bux Guest

    Steve555 wrote:

    > Hi,
    >
    > Given a struct:
    >
    > struct myStruct{
    > int a;
    > float b;
    > };
    >
    > and given a vector containing them, how do I get a ptr to one while
    > iterating through that vector:
    >
    > myStruct *myStructPtr;
    > vector<myStruct>::iterator iter;
    > for(iter = myStructVec.begin(); iter != myStructVec.end(); ++ iter)
    > {
    > myStructPtr = iter; (???
    > ChangeStructValuesFunction( myStructPtr );
    > ...
    > }


    You can obtain a pointer by taking the address of the pointee:

    myStructPtr = &*iter;

    > The goal is to modify a & b in-place.


    If that is the goal, the signature of ChangeStructValuesFunction() should
    be:

    ChangeStructValuesFunction( myStruct & my_struct );

    Then, you could just do:

    ChangeStructValuesFunction( *iter );

    [snip]


    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, Dec 26, 2008
    #4
  5. Steve555

    Steve555 Guest

    On 26 Dec, 09:53, Kai-Uwe Bux <> wrote:
    > Steve555 wrote:
    > > Hi,

    >
    > > Given a struct:

    >
    > > struct myStruct{
    > > int   a;
    > > float b;
    > > };

    >
    > > and given a vector containing them, how do I get a ptr to one while
    > > iterating through that vector:

    >
    > > myStruct  *myStructPtr;
    > > vector<myStruct>::iterator   iter;
    > > for(iter = myStructVec.begin(); iter != myStructVec.end(); ++ iter)
    > >  {
    > >         myStructPtr = iter;  (???
    > >        ChangeStructValuesFunction( myStructPtr );
    > >        ...
    > > }

    >
    > You can obtain a pointer by taking the address of the pointee:
    >
    >   myStructPtr = &*iter;
    >
    > > The goal is to modify a & b in-place.

    >
    > If that is the goal, the signature of ChangeStructValuesFunction() should
    > be:
    >
    >   ChangeStructValuesFunction( myStruct & my_struct );
    >
    > Then, you could just do:
    >
    >   ChangeStructValuesFunction( *iter );
    >
    > [snip]
    >
    > Best
    >
    > Kai-Uwe Bux


    Thanks for everyone's help.
    Of course I should have tried &*iter, but I'd got side-tracked and
    reasoned that as iter is a kind of pointer, I could just cast:
    myStructPtr = (myStruct*)iter

    I've modified my function as suggested to accept *iter, which is a
    great new technique for me as I've been needlessly dereferencing
    iters in many other situations.

    Steve
    Steve555, Dec 26, 2008
    #5
  6. Steve555

    red floyd Guest

    On Dec 26, 1:53 am, Kai-Uwe Bux <> wrote:
    > Steve555 wrote:
    > > Hi,

    >
    > > Given a struct:

    >
    > > struct myStruct{
    > > int   a;
    > > float b;
    > > };

    >
    > > and given a vector containing them, how do I get a ptr to one while
    > > iterating through that vector:

    >
    > > myStruct  *myStructPtr;
    > > vector<myStruct>::iterator   iter;
    > > for(iter = myStructVec.begin(); iter != myStructVec.end(); ++ iter)
    > >  {
    > >         myStructPtr = iter;  (???
    > >        ChangeStructValuesFunction( myStructPtr );
    > >        ...
    > > }

    >
    > You can obtain a pointer by taking the address of the pointee:
    >
    >   myStructPtr = &*iter;
    >
    > > The goal is to modify a & b in-place.

    >
    > If that is the goal, the signature of ChangeStructValuesFunction() should
    > be:
    >
    >   ChangeStructValuesFunction( myStruct & my_struct );
    >
    > Then, you could just do:
    >
    >   ChangeStructValuesFunction( *iter );
    >


    always assuming, of course, that myStruct hasn't redefined operator&.
    red floyd, Dec 26, 2008
    #6
  7. Steve555

    Kai-Uwe Bux Guest

    red floyd wrote:

    > On Dec 26, 1:53 am, Kai-Uwe Bux <> wrote:
    >> Steve555 wrote:
    >> > Hi,

    >>
    >> > Given a struct:

    >>
    >> > struct myStruct{
    >> > int   a;
    >> > float b;
    >> > };

    >>
    >> > and given a vector containing them, how do I get a ptr to one while
    >> > iterating through that vector:

    >>
    >> > myStruct  *myStructPtr;
    >> > vector<myStruct>::iterator   iter;
    >> > for(iter = myStructVec.begin(); iter != myStructVec.end(); ++ iter)
    >> > {
    >> > myStructPtr = iter;  (???
    >> > ChangeStructValuesFunction( myStructPtr );
    >> > ...
    >> > }

    >>
    >> You can obtain a pointer by taking the address of the pointee:
    >>
    >> myStructPtr = &*iter;


    (***)

    >> > The goal is to modify a & b in-place.

    >>
    >> If that is the goal, the signature of ChangeStructValuesFunction() should
    >> be:
    >>
    >> ChangeStructValuesFunction( myStruct & my_struct );
    >>
    >> Then, you could just do:
    >>
    >> ChangeStructValuesFunction( *iter );
    >>

    >
    > always assuming, of course, that myStruct hasn't redefined operator&.


    (a) I think, this comment is misplaced. It should be put at the position
    marked with (***), since operator& is inconsequential for whether

    ChangeStructValuesFunction( *iter );

    will work.


    (b) Fortunately, we were given the definition of myStruct :)

    Anyway, you are correct that an overloaded operator& can be a problem.
    Instead of &*iter, one could always use address_of( *iter ) where:

    // stolen from Boost:
    template < typename T >
    T * address_of ( T & t ) {
    return (
    reinterpret_cast<T*>(
    & const_cast<char&>(
    reinterpret_cast<const volatile char &>( t ) ) ) );
    }

    This might be a good idea for templated code that has to cope with user
    defined types.


    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, Dec 26, 2008
    #7
  8. Steve555

    Bo Persson Guest

    Steve555 wrote:
    > Of course I should have tried &*iter, but I'd got side-tracked and
    > reasoned that as iter is a kind of pointer,


    It is actually the other way round - a pointer is a kind of random
    access iterator!

    > I could just cast:
    > myStructPtr = (myStruct*)iter


    Casts are most often bad, and tells the compiler to "just shut up and
    do it!". Whether it actually works or not...


    Bo Persson
    Bo Persson, Dec 26, 2008
    #8
  9. Steve555

    Steve555 Guest

    On 26 Dec, 23:38, "Bo Persson" <> wrote:
    > Steve555 wrote:
    > > Of course I should have tried &*iter, but I'd got side-tracked and
    > > reasoned that as iter is a kind of pointer,

    >
    > It is actually the other way round - a pointer is a kind of random
    > access iterator!
    >
    > > I could just cast:
    > > myStructPtr = (myStruct*)iter

    >
    > Casts are most often bad, and tells the compiler to "just shut up and
    > do it!". Whether it actually works or not...
    >
    > Bo Persson


    Quite... well learning the hard way is the best way!
    Heh,heh, I want to edit my compiler resources so the "Build" button
    becomes a "Just shut up and do it!" button :)
    Steve555, Dec 27, 2008
    #9
  10. Steve555

    James Kanze Guest

    On Dec 27, 6:28 am, Steve555 <> wrote:
    > On 26 Dec, 23:38, "Bo Persson" <> wrote:


    > Heh,heh, I want to edit my compiler resources so the "Build"
    > button becomes a "Just shut up and do it!" button :)


    I'm still looking for a system which has a "do what I meant, not
    what I said" configuration option.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Dec 27, 2008
    #10
  11. Steve555

    James Kanze Guest

    On Dec 29, 8:06 am, (blargg) wrote:
    > Bo Persson wrote:
    > > Steve555 wrote:
    > > > Of course I should have tried &*iter, but I'd got side-tracked and
    > > > reasoned that as iter is a kind of pointer,


    > > It is actually the other way round - a pointer is a kind of
    > > random access iterator!


    > > > I could just cast:
    > > > myStructPtr = (myStruct*)iter


    > > Casts are most often bad, and tells the compiler to "just
    > > shut up and do it!". Whether it actually works or not...


    > Especially old-style casts. If an inexperienced C++ programmer
    > feels he must cast, he should stick to static_cast unless he
    > knows for certain. Even then, static_cast requires care when
    > downcasting.


    Actually, the beginning programmer should stick to dynamic_cast
    whenever pointers or references are concerned. (I have no real
    problems with C style casts otherwise, but it's really a style
    issue.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Dec 29, 2008
    #11
  12. Steve555

    peter koch Guest

    On 29 Dec., 11:06, James Kanze <> wrote:
    > On Dec 29, 8:06 am, (blargg) wrote:

    [snip]
    > > Especially old-style casts. If an inexperienced C++ programmer
    > > feels he must cast, he should stick to static_cast unless he
    > > knows for certain.  Even then, static_cast requires care when
    > > downcasting.

    >
    > Actually, the beginning programmer should stick to dynamic_cast
    > whenever pointers or references are concerned.  (I have no real
    > problems with C style casts otherwise, but it's really a style
    > issue.)


    That must be because you know what you're doing so much better than
    the rest of us ;-)

    I almost never use C-style casting, and whenever I see one it gives me
    a creeping feeling that something fishy might take place. The never
    casts gives me more confidence in the code although I would have
    preferred the restrictions to be even stronger for static_cast.
    One exception to this is the "constructor cast": int i = int(4.7). I
    really would have loved it if this cast had been as safe as a
    static_cast.

    /Peter
    peter koch, Dec 29, 2008
    #12
  13. Steve555

    James Kanze Guest

    On Dec 29, 1:25 pm, peter koch <> wrote:
    > On 29 Dec., 11:06, James Kanze <> wrote:


    > > On Dec 29, 8:06 am, (blargg) wrote:

    > [snip]
    > > > Especially old-style casts. If an inexperienced C++
    > > > programmer feels he must cast, he should stick to
    > > > static_cast unless he knows for certain. Even then,
    > > > static_cast requires care when downcasting.


    > > Actually, the beginning programmer should stick to
    > > dynamic_cast whenever pointers or references are concerned.
    > > (I have no real problems with C style casts otherwise, but
    > > it's really a style issue.)


    > That must be because you know what you're doing so much better
    > than the rest of us ;-)


    You mean that I'm consciously aware that I'm using a different
    style of cast that the new casts.

    > I almost never use C-style casting, and whenever I see one it
    > gives me a creeping feeling that something fishy might take
    > place.


    C-style, perhaps, but I'll bet you do write things like
    MyClass( 42 ), where MyClass has a constructor which takes an
    int. And that's a function style cast, which has exactly the
    same behavior as a C-style cast. Given that, things like
    double( 42 ) don't bother me either. And of course, if the type
    name requires more than a single token, it becomes (long
    double)( 42 ). Which, formally, is a C-style cast.

    My point, of course, is that all of the code I've ever seen uses
    things like MyClass( 42 ). And MyClass(), if there is a default
    constructor, and MyClass( 1, 2, 3 ) if there is a constructor
    taking three ints, etc. In practice, I think that most people
    don't think of it as a "type conversion" (although that's what
    the standard calls it); they think of it as explicitly creating
    a temporary of the given type. Or at least, that's the way I
    think of it. And double( 42 ) is also explicitly creating a
    temporary of type double---it happens that double has a
    constructor taking a single argument. And that I find it
    difficult to accept double( 42 ), but reject
    (long double)( 42 ), just on the grounds that it has an extra
    set of parentheses. And of course, if you accept
    (long double)( 42 ), then you really have to accept
    (double)( 42 ).

    I don't use things like (double)42, without what is being
    converted in parentheses.

    > The never casts gives me more confidence in the code although
    > I would have preferred the restrictions to be even stronger
    > for static_cast.


    Let's say that I'd prefer a few other types of casts, e.g.
    checked_cast, etc.

    > One exception to this is the "constructor cast": int i =
    > int(4.7). I really would have loved it if this cast had been
    > as safe as a static_cast.


    Unless pointers and references are involved, it *is* a
    static_cast (with perhaps a const_cast thrown in).

    The issue isn't simple, and I can understand your desire to make
    such things stand out. The problem is that you can't, really.
    MyClass( 4.7 ) is going to work, even if MyClass only has a
    constructor which takes an int, and there's nothing you can do
    about it. This is a serious flaw in the language, but one that,
    for practical considerations of backwards compatibility, can't
    really be fixed. (There was once a proposal to deprecate
    implicit lossy conversions, like this. It didn't pass, despite
    the fact that the person who proposed it, Bjarne Stroustrup,
    justifiably had a great deal of influence in the committee.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Dec 29, 2008
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Sid
    Replies:
    5
    Views:
    1,065
  2. Heiko Vogel
    Replies:
    3
    Views:
    548
    Method Man
    Sep 14, 2004
  3. franco ziade

    const ptr to const ptr ?

    franco ziade, Feb 17, 2005, in forum: C Programming
    Replies:
    3
    Views:
    387
    franco ziade
    Feb 17, 2005
  4. Replies:
    8
    Views:
    1,896
    Csaba
    Feb 18, 2006
  5. zl2k
    Replies:
    27
    Views:
    1,558
    Francesco S. Carta
    Sep 7, 2010
Loading...

Share This Page