Assign a structure to an iterator

S

steflhermitte

Dear cpp-ians,

I am working with a structure

struct segment
{
....
vector <meta_segment>::iterator it_Z;
....
};

and a variable of that type:

segment *** output;

I also have a pointer to an element of a vector

meta_segment * Z;

Now I want to assign the address of Z to the iterator Z:

output[y][y]->it_Z = Z;

but it does not work.

I assume the problem is my missunderstanding of the concept of pointers
and iterators. My rationing goes as follows:
- Iterators are generalized pointers that allow me to navigate in
vectors.
- Iterators are consequently the adresses of the elements of my vector.
- output[y][y]->it_Z has to be the adress of a meta_segment
- Z is a pointer to (= the address of) a meta_segment

Where do I go wrong? Or why the assignment to output[y][y]->it_Z fails?

Thanks in advance! Kind regards,
Stef
 
V

Victor Bazarov

steflhermitte said:
I am working with a structure

struct segment
{
...
vector <meta_segment>::iterator it_Z;
...
};

and a variable of that type:

segment *** output;

This seems to be not "of that type" but of the type "a pointer to
a pointer to a pointer of that type"...
I also have a pointer to an element of a vector

meta_segment * Z;

Now I want to assign the address of Z to the iterator Z:

output[y][y]->it_Z = Z;

but it does not work.

Probably because iterators cannot be assigned from pointers.
I assume the problem is my missunderstanding of the concept of pointers
and iterators.

Probably. Have you tried treating them differently?
My rationing goes as follows:
- Iterators are generalized pointers that allow me to navigate in
vectors.

No. Iterators are iterators. Pointers are a special case of iterators.
Iterator (and there are several types of them) as a concept allows you to
identify an element of a collection and perform some (different depending
on the type of the iterator) operations: extraction, assignment, advance,
etc. Pointers are a particular case of random-access iterators, often
used with elements of C++ _arrays_. Pointers conform to the random-access
iterators semantics, but iterators and pointers are not the same thing.
- Iterators are consequently the adresses of the elements of my vector.

Huh? No, they are not. They are objects associated [in some particular
way] with elements of a vector. Or a set. Or a map. Or with contents
of a stream.
- output[y][y]->it_Z has to be the adress of a meta_segment

"Has to be"? No, it's an iterator. It's an object of type "iterator to
[an element of] a vector".
- Z is a pointer to (= the address of) a meta_segment

Well, this one is true, I suppose.
Where do I go wrong? Or why the assignment to output[y][y]->it_Z fails?

There is no guarantee that 'Z' is an element of a vector. Why should the
iterator accept that assignment?

I have the following analogy for you. Take a troop of soldiers, they are
all men, for simplicity. Now I have a man. I just call him a soldier and
tell him to follow orders. He won't. Just because he's a man does not
mean he's a soldier. Just because something is a pointer to object T does
not mean it's an iterator to an element of a vector of T.

V
 
J

John Carson

steflhermitte said:
Dear cpp-ians,

I am working with a structure

struct segment
{
...
vector <meta_segment>::iterator it_Z;
...
};

and a variable of that type:

segment *** output;

I also have a pointer to an element of a vector

meta_segment * Z;

Now I want to assign the address of Z to the iterator Z:

output[y][y]->it_Z = Z;

but it does not work.

I assume the problem is my missunderstanding of the concept of
pointers and iterators. My rationing goes as follows:
- Iterators are generalized pointers that allow me to navigate in
vectors.
- Iterators are consequently the adresses of the elements of my
vector.
Wrong.

- output[y][y]->it_Z has to be the adress of a meta_segment
Wrong.

- Z is a pointer to (= the address of) a meta_segment

Where do I go wrong? Or why the assignment to output[y][y]->it_Z
fails?

An iterator is an object of a class that behaves in a pointer-like way in
some respects, but in most cases it is not a pointer, i.e., it is not an
address.

Given an iterator, it, that allows you to iterate over objects of type T,
you can always go from the iterator to an address as follows:

T * ptr = &(*it);

However, the reverse procedure is not generally possible. With vectors,
however, it is possible. Given a pointer to an arbitrary element, e, of a
vector, v, you can get the iterator that points to element e by starting
with v.begin() and adding to it the difference between the pointer to e and
the pointer to the first element of v.

We can get the pointer to the first element of v in either of two ways:

T *begin_ptr = &v[0];

or

T *begin_ptr = &(*v.begin());

If e_ptr points to e, then the iterator that points to e is:

v.begin() + (e_ptr - begin_ptr);

You haven't shown where the vector of meta_segments is defined, but let us
call this vector vms. Then we have:

meta_segment * begin_ptr = &vms[0];

or

meta_segment * begin_ptr = &(*vms.begin());

You can them make your assignment as follows:

output[y][y]->it_Z = vms.begin() + (Z - begin_ptr);

since the right hand side is the iterator pointing to whatever Z points to.

Whether this is the most elegant way of handling whatever it is that you are
handling is another matter.
 
D

Default User

steflhermitte said:
Dear cpp-ians,

I am working with a structure

struct segment
{
...
vector <meta_segment>::iterator it_Z;
...
};


Besides what Victor and John said, I'm extremely dubious about what you
are even trying to do. Iterators a very bad thing to try and store
anywhere, especially in some decoupled data structure. Many operations
on vectors result in a resize, which will likely invalidate all
interators (or pointers).

What are you trying to do? Tell us your problem, not your broken
solution. I doubt highly this is the right way to do things.



Brian
 
S

steflhermitte

Thank you very much for your help.

I will explain shortly what I am doing. I explained it also in previous
postst to the forum, but here is a short overview.

I am writing an image segmentation program based on a multi-resolution
technique. Multi-resolution segmentation is a bottom up region-merging
technique starting with one-pixel objects. In numerous subsequent
steps, smaller image objects are merged into bigger ones. In each step,
that pair of adjacent image objects is merged which stands for the
smallest growth of the defined heterogeneity. So what happens. I first
merge single pixels into couples. Afterwards I start merging the
couples into groups of four and so on. Once a defined heterogeneity is
reached for an object (=full), it does not participate any longer in
the process till all objects are full.

How does this look like in C++:

Is started with a vector X (nrow x ncol) and the
elements are structures :
struct meta_segment
{ ...
struct segment * group;
// Group is a pointer to an array Y[nrow][ncol]
...};
and array Y[nrow][ncol] is an image and the pixels are structures:
struct segment
{ ...
struct meta_segment * meta_segm;
// Meta-segm is a pointer to the vector X
...};

So X and Y both point to eachother.

Now I wanted the program to work as follows:
1. Pick a random A out of vector X
2. A->group in X points to pixels a in Y
3. Search the pixels b in Y that are the closest to a. I have written
this, and get the coordinates of b in Y as result.
4. b->meta-segm points to B in X
5. Merge A and B (+ a and b) by:
* removing A and B out of X and putting them in another vector C
in X2(using push_back)
* replacing the pointers:
- C->group points to a and b
- a->meta-segm and b->meta-segm point to C
This is done till X is empty, and then the process is repeated for X2
and so on.

The discussion forum proposed to change my array Y so that is does not
point anymore to the vector X, but has the value of the iterator of X.

array Y[nrow][ncol] is an image and the pixels are structures:
struct segment
{ ...
vector <meta_segment>::iterator it_meta_segment;
// It_meta-segm is an iterator of the vector X
...};

Besides, they proposed to use a 2nd vector. This vector Z consists of
pointers to the original vector X. In this way I do not need to remove
elements out of X, but I can remove them out of Z. This must allow me
to keep X constant in size and avoid that my iterators become invalid.
As such I don't get the problems that would occur if I resize my
vector.

In C++:

/* Declare Z (vector of pointers to vector X) and his associated
iterator */
vector <meta_segment *> Z;
vector <meta_segment *>::iterator it_Z;

/* Assign Z with "pointers to X" */
for(it_X = X.begin(); it_X != X.end(); it_X++ )
{
Z.push_back(&(*it_X));
}

/* I have a function that works with the data of X */
void f_1 (meta_segment * it_X)
{
...
/* In this function I wanted to do the assignment of the beginning
of this topic */
}

I hope this explains my problem a bit clearer.

Kind regards,
Stef
 

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,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top