Connecting Tech Pros Worldwide Forums | Help | Site Map

Initializing a vector with pointers to elements of another

Matthias
Guest
 
Posts: n/a
#1: Jul 23 '05
Hi,

say I have a vector v1:

std::vector<SomeType> v1;

and I need a vector v2 of pointers to v1's elements:

std::vector<SomeType*> v2;

std::vector<SomeType>::iterator iter;
for( iter = v1.begin(); iter != v1.end(), ++iter )
v2.push_back( &(*iter) );


Now is there a more elegant way to initialize v2 instead of looping
through v1 and pushing back the *iter's address to v2?
Something like "for each elem in v1 insert its address into v2"?
Having a loop which only consists of a single insert operation, I have
the feeling this may be better expressed with some STL algo.

--
Regards,
Matthias

Mike Wahler
Guest
 
Posts: n/a
#2: Jul 23 '05

re: Initializing a vector with pointers to elements of another


"Matthias" <nospam@digitalraid.com> wrote in message
news:cu8nli$rm0$01$1@news.t-online.com...[color=blue]
> Hi,
>
> say I have a vector v1:
>
> std::vector<SomeType> v1;
>
> and I need a vector v2 of pointers to v1's elements:
>
> std::vector<SomeType*> v2;
>
> std::vector<SomeType>::iterator iter;
> for( iter = v1.begin(); iter != v1.end(), ++iter )
> v2.push_back( &(*iter) );
>
>
> Now is there a more elegant way to initialize v2 instead of looping
> through v1 and pushing back the *iter's address to v2?
> Something like "for each elem in v1 insert its address into v2"?
> Having a loop which only consists of a single insert operation, I have
> the feeling this may be better expressed with some STL algo.[/color]

You could use 'std::for_each()' with a functor, but imo it's
probably not worth the trouble. You might just want to wrap
that loop up into a function with references to the two vectors
as parameters, then just call from your 'main' logic. Here's the
'for_each' code just for fun anyway:


#include <algorithm>
#include <vector>

class ftor
{
std::vector<int*>& v;
public:
ftor(std::vector<int*>& arg) : v(arg)
{
}

void operator()(int& i)
{
v.push_back(&i);
}
};

int main()
{
std::vector<int> vec;
for(int i = 0; i < 5; ++i)
vec.push_back(i);

std::vector<int*> pvec;
std::for_each(vec.begin(), vec.end(), ftor(pvec));

return 0;
}

Another possiblity (if your element type is user-defined), is
to define a conversion from T to T*, and use 'std::copy' (not
possible if the element type is a built-in type):

#include <algorithm>
#include <vector>

class C
{
public:
operator C*()
{
return this;
}
};

int main()
{
std::vector<C> cvec;
for(int i = 0; i < 5; ++i)
{
cvec.push_back(C());
}

std::vector<C*> pvec;

std::copy(cvec.begin(), cvec.end(),
std::back_inserter(pvec));

return 0;
}

However I consider this dangerous, as the automatic conversion
from C to C* could mask errors elsewhere.

Having said all the above, BE WARNED: No matter which way you
store your pointers (with a 'plain' loop, either of the ways
I've shown, or any other way), note that if you later modify
the vector of whose elements you're storing their addresses,
and the vector is later modified, the elements could be moved
due to reallocation, invalidating the address values stored
in the other vector. I'd consider doing what you're
asking about only if the first vector is const (in which
case you'd have to load it via a ctor, since you wouln't
be able to 'push_back' the elements. Or if it's not const,
you'd need to reset and reload the pointer vector every time
the first vector gets changed. An awful lot of work. :-)



-Mike


red floyd
Guest
 
Posts: n/a
#3: Jul 23 '05

re: Initializing a vector with pointers to elements of another


Matthias wrote:[color=blue]
> Hi,
>
> say I have a vector v1:
>
> std::vector<SomeType> v1;
>
> and I need a vector v2 of pointers to v1's elements:
>
> std::vector<SomeType*> v2;
>
> std::vector<SomeType>::iterator iter;
> for( iter = v1.begin(); iter != v1.end(), ++iter )
> v2.push_back( &(*iter) );
>
>
> Now is there a more elegant way to initialize v2 instead of looping
> through v1 and pushing back the *iter's address to v2?
> Something like "for each elem in v1 insert its address into v2"?
> Having a loop which only consists of a single insert operation, I have
> the feeling this may be better expressed with some STL algo.
>[/color]

struct addressor {
SomeType* operator()(SomeType& s) const { return &s; }
const SomeType* operator()(const SomeType& s) const { return &s; }
};

/// ...

std::transform(v1.begin(), v1.end(),
std::back_inserter(v2),
addressor());

red floyd
Guest
 
Posts: n/a
#4: Jul 23 '05

re: Initializing a vector with pointers to elements of another


red floyd wrote:[color=blue]
> Matthias wrote:
>[color=green]
>> Hi,
>>
>> say I have a vector v1:
>>
>> std::vector<SomeType> v1;
>>
>> and I need a vector v2 of pointers to v1's elements:
>>
>> std::vector<SomeType*> v2;
>>
>> std::vector<SomeType>::iterator iter;
>> for( iter = v1.begin(); iter != v1.end(), ++iter )
>> v2.push_back( &(*iter) );
>>
>>
>> Now is there a more elegant way to initialize v2 instead of looping
>> through v1 and pushing back the *iter's address to v2?
>> Something like "for each elem in v1 insert its address into v2"?
>> Having a loop which only consists of a single insert operation, I have
>> the feeling this may be better expressed with some STL algo.
>>[/color]
>
> struct addressor {
> SomeType* operator()(SomeType& s) const { return &s; }
> const SomeType* operator()(const SomeType& s) const { return &s; }
> };
>
> /// ...
>
> std::transform(v1.begin(), v1.end(),
> std::back_inserter(v2),
> addressor());
>[/color]

That said, storing *addresses* of vector elements is a "bad idea"(tm).
You have the same problem as storing iterators to the elements -- they
can be invalidated should the vector need to reallocate itself.
Better to store the indices instead. i.e.

std::vector<std::vector<SomeType>::size_type> v2;

for (std::vector<SomeType>::size_type> i = 0 ; i < v1.size(); ++i)
v2.push_back(i);


Matthias
Guest
 
Posts: n/a
#5: Jul 23 '05

re: Initializing a vector with pointers to elements of another


Thanks for your answers.

As to the overall pointer question:
I want to store pointers, because I need to sort the elements, and I
thought I'd be better to sort pointers instead of the objects themselves
for performance reasons. At least that's what the guys over at
comp.programming suggested.

On the other hand, the actual objects are boost pathS, which only
consist of a single string object IIRC (the rest of the path class are
operations).

Is it worth the inconvenience at all to sort pointers to path objects
instead of sorting the pathS themselves? How expensive is it to copy a
path object?

--
Regards,
Matthias
msalters
Guest
 
Posts: n/a
#6: Jul 23 '05

re: Initializing a vector with pointers to elements of another



Matthias wrote:[color=blue]
> Thanks for your answers.
>
> As to the overall pointer question:
> I want to store pointers, because I need to sort the elements, and I
> thought I'd be better to sort pointers instead of the objects[/color]
themselves[color=blue]
> for performance reasons. At least that's what the guys over at
> comp.programming suggested.[/color]

Well, over here we'd say, profile, and optimize only if needed, and
then profile again to check you actually gained something.

The problem is that swapping two T's may be more expensive then
checking two T*s, but this is not always the case. In particular,
swapping two strings or similar objects is often just as expensive:
a common string implementation is just a pointer+size. Swapping those
is twice the work of swapping two pointers, which is balanced by
the reduction in indirection.
[color=blue]
> Is it worth the inconvenience at all to sort pointers to path objects[/color]
[color=blue]
> instead of sorting the pathS themselves? How expensive is it to copy[/color]
a[color=blue]
> path object?[/color]

Doesn't matter much, the price of swaps tends to dominate.

HTH,
Michiel Salters

Matthias
Guest
 
Posts: n/a
#7: Jul 23 '05

re: Initializing a vector with pointers to elements of another


msalters wrote:[color=blue]
> Matthias wrote:
>[color=green]
>>Thanks for your answers.
>>
>>As to the overall pointer question:
>>I want to store pointers, because I need to sort the elements, and I
>>thought I'd be better to sort pointers instead of the objects[/color]
>
> themselves
>[color=green]
>>for performance reasons. At least that's what the guys over at
>>comp.programming suggested.[/color]
>
>
> Well, over here we'd say, profile, and optimize only if needed, and
> then profile again to check you actually gained something.
>
> The problem is that swapping two T's may be more expensive then
> checking two T*s, but this is not always the case. In particular,
> swapping two strings or similar objects is often just as expensive:
> a common string implementation is just a pointer+size. Swapping those
> is twice the work of swapping two pointers, which is balanced by
> the reduction in indirection.
>
>[color=green]
>>Is it worth the inconvenience at all to sort pointers to path objects[/color]
>
>[color=green]
>>instead of sorting the pathS themselves? How expensive is it to copy[/color]
>
> a
>[color=green]
>>path object?[/color]
>
>
> Doesn't matter much, the price of swaps tends to dominate.
>
> HTH,
> Michiel Salters
>[/color]

So, there's no reason to sort a list of pointers, because the sort
itself is expensive for both path and "pointer to path"?
Is that what you mean?

--
Regards,
Matthias
Closed Thread