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
iter->a = 42;
--
Ian Collins
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:james...@gmail.com
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
> 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
always assuming, of course, that myStruct hasn't redefined operator&.
> On Dec 26, 1:53 am, Kai-Uwe Bux <jkherci...@gmx.net> 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
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 :-)
I'm still looking for a system which has a "do what I meant, not
what I said" configuration option.
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
> > On Dec 29, 8:06 am, blargg....@gishpuppy.com (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.)