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

S

Steve555

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
 
I

Ian Collins

Steve555 said:
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;
 
J

James Kanze

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.
 
K

Kai-Uwe Bux

Steve555 said:
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
 
S

Steve555

Steve555 said:
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
 
R

red floyd

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

  myStructPtr = &*iter;


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&.
 
K

Kai-Uwe Bux

red said:
(***)


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
 
B

Bo Persson

Steve555 said:
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
 
S

Steve555

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


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 :)
 
J

James Kanze

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.)
 
P

peter koch

On Dec 29, 8:06 am, (e-mail address removed) (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
 
J

James Kanze

On Dec 29, 8:06 am, (e-mail address removed) (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.)
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,817
Latest member
DicWeils

Latest Threads

Top