tags:

views:

562

answers:

4

Ok so I have struct like this

typedef struct
{
float x;
float y;
char name[];
} pTip;

And another struc

typdef struct
{
    float xx;
    float yy;
    pTip *tip;
}finalTip;

I create and populate a map<string, pTip> maps

That works fine. I am now trying to generate vector of finalTips

I do:

map<string, pTip>::const_iterator iter = maps.find(p_name);

So it works great my iterator now has what I need and I can extract info with

(iter->second).x

But I want to now using that iterator save it in my finalTip struc obj final So I tried:

finalTip final;
final.tip = iter->second;

And for this case I get error:

error: cannot convert 'const pTip' to 'pTip*' in assignment

So I fixed by:

*final.tip = iter->second;

Was this correct fix or am I doing it wrong. This seems to work but I want to make sure I am doing it right

A: 

Had you initialized final.tip to point to an "empty" tip...? Otherwise you're copying into uninitialized memory. Maybe you mean final.tip = new pTip(iter->second), i.e., a copy constructor into newly allocated storage? Also be careful about that char name[] construct -- without a length there, an automatically generated copy constructor may be in trouble doing things right, so you may need to explicitly code the copy ctor you need!

Alex Martelli
the `char name[]` construct would be a non-standard thing, so you're right that he needs to take care on that (MSC will not autogenerate a copy ctor or assignment operator for such structs).
Michael Burr
in particular, if he keeps it in a map, then i can only see failure coming out of it. calling insert and then when the map copies it, won't it cut off the parts that `name` usually is supposed to overlay? Not sure how MSVC would handle that.
Johannes Schaub - litb
A: 

I am surprised this works. Unless you have a code that initializes final.tip that you have shown here, this would write the value of iter->second in a random place in the memory, which can lead to unpredictable results.

Franci Penov
A: 

This code:

*final.tip = iter->second

is quite likely to eventually cause your program to start behaving erratically. You are stomping on memory. final.tip is an uninitialized pointer and it could be pointing anywhere. You are causing wherever it's pointing to be overwritten with the contents of iter->second.

I'm not completely sure what you want to accomplish here. The answer to your question is highly dependent on this.

The char name[] construct in pTip is also interesting and problematic. It looks like you're trying to use a stretchy buffer at the end of your structure, which is a common C technique. That is unlikely to work well when mixed with STL containers.

My suspicion is that you intend your map to map to pointers instead of struct copies. I suspect you meant something more like:

typedef struct
{
float x;
float y;
char name[];
} *pTip;
Omnifarious
+4  A: 

You want

final.tip = &iter->second;

Since iter is a map<string, pTip> iterator, iter->second is a reference to pTip. Take its address with & to get a pointer.

Unfortunately, since you have a const_iterator, &iter->second will be a (const pTip *)

So, either get a non-const iterator, or make the .tip member a const pTip *, or if you're desperate, cast away the const:

final.tip = const_cast<pTip*>(&iter->second);

Final note: you may prefer pTip const* to const pTip * - they mean the same thing.

wrang-wrang
This does not fit the fact that he has a stretchy buffer at the end of pTip. I think he means for pTip to be a pointer and consequently for the map elements to be pointers.
Omnifarious
It's confusing, I admit, but Map will in fact be implemented as a node data structure of some sort. Iterators won't be invalidated by operations on the tree (other than deleting the item). So it's legitimate to keep a pointer to the mapped item (without needing the map to hold pointers to standalone objects on the heap). This is contrary to say, taking the address of a vector iterator, where resizing would invalidate the pointer.
wrang-wrang
@wrang-wang - I don't find it confusing. I figured that the pointer you got would still point at something valid after the iterator went away, though I think relying on the kind of behavior is a little precarious. My complaint is that the pTip structure doesn't look like it should be stored by value at all. It has what looks like a stretchy buffer at the end.
Omnifarious
You're right, I didn't look at what was in pTip. A pTip should never be held by value in a standard container if the stretchy part is nonempty.
wrang-wrang