views:

123

answers:

3

I'm a little bit scared about something like this:

std::map<DWORD, DWORD> tmap;
  tmap[0]+=1;
  tmap[0]+=1;
  tmap[0]+=1;

Since DWORD's are not automatically initialized, I'm always afraid of tmap[0] being a random number that is incremented. How does the map know hot to initialize a DWORD if the runtime does not know how to do it?

Is it guaranteed, that the result is always tmap[0] == 3?

+4  A: 

Yes. When a new value is inserted into a map by operator[] it is value-initialized and for built-in numeric types (DWORD is a typedef for built-in type) this means zero.

Charles Bailey
A: 

Yes. If the key you passed to operator[] doesnot exist, then map will default construct the object and inserts it. In your case it will do DWORD() which will yield a value 0.

Naveen
+3  A: 

The new object, when inserted into the map by [] operator, is value-initialized. It is ensured by the map implementation, i.e. it is done "automatically" in that sense. For objects of type DWORD (assuming it is a scalar type), value-initialization means zero-initialization.

By definition given in 23.3.1.2, operator [] is a shorthand for

(*((insert(make_pair(x, T()))).first)).second

The T() bit is the new object, which will turn into DWORD() in your case. DWORD() is guaranteed to be zero.

AndreyT
I was really not aware of value-initialization existing for built-in data types. That makes my life easier!
I see. But if the default constructor of type T is expensive and the map already contains key x, then this "shorthand" is painfully ineffective! Or am I wrong??
@thomas-gies: You are right, it will indeed be ineffective if implemented literally as shown above. I would expect a quality implementation to somehow implement *equivalent* functionality in a more reasonable way.
AndreyT
MSalters
@MSalters: Yes, but Thomas was specifically talking about the situation when the key is already in the map (how it got there - doesn't matter), i.e. `U` part already exists. In that case the literal implementation will unconditionally pre-construct an absolutely unnecessary `U()`, then discover that it is not needed and destroy it. This useless construction-destruction of `U()` is something a quality implementation can probably avoid by running the key-already-in-the-map check first.
AndreyT
@AndreyT: Implementations are allowed to eliminate some copy-constructed temporaries in some circumstances. I don't know of any case where they are allowed to eliminate the a _value-initialized_ temporary (even if it is initialized into a different object to eliminate the copy). As far as I can see, this _value-initialized_ temporary is mandated in the contract for `map::operator[]` . Am I missing something?
Charles Bailey
@Charles Bailey: I believe you are wrong about elimination. You are saying "eliminate some copy-constructed temporaries". I believe this is not accurate. The more accurate description is: the implementation is allowed to eliminate temporaries that exist only to be copied (and immediately destroyed afterwards).
AndreyT
@Charles Bailey: Now, whether this permission to eliminate applies to the above case with `operator []` I'm not really sure. For example, if the default constructor of the type `T` has side effects, is the implementation allowed not to create a `T()` temporary when the key is already in the map? In case of the aforementioned temporary optimization, the side effects are allowed to be ignored. But in case of the standard specification of `operator []`, I'm not sure. I'd only say that this a natural thing to allow.
AndreyT
BTW, it turns out it is a known issue, Library Defect #334 http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#334
AndreyT
Yes, my wording was loose. I meant that I don't know of any place where it's valid to eliminate an initialization that isn't a copy. You can eliminate a _value-initialized_ temporary by directly value-initializing an object that would have been copy- (or direct- ??) initialized from that temporary but it was my understanding that the value-initialization can't be eliminated entirely, only transposed.
Charles Bailey