Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
219 views
in Technique[技术] by (71.8m points)

c++ - Is indexing a new map element and having something that reads it assigned to it undefined behaviour, or just unspecified?

After answering this question, there was a long discussion over whether the code in question was undefined behaviour or not. Here's the code:

std::map<string, size_t> word_count;
word_count["a"] = word_count.count("a") == 0 ? 1 : 2;

First of all, it was well-established that this was at least unspecified. The result differs based on which side of the assignment is evaluated first. In my answer, I followed through each of the four resulting cases, with factors of which side is evaluated first and whether the element exists prior to this.

There was a short form that came up as well:

(x = 0) = (x == 0) ? 1 : 2; //started as
(x = 0) = (y == "a") ? 1 : 2; //changed to

I claimed it was more like this:

(x = 0, x) = (x == 0) ? 1 : 2; //comma sequences x, like [] should

Eventually, I found an example that seemed to work for me:

i = (++i,i++,i); //well-defined per SO:Undefined Behaviour and Sequence Points

Back to the original, I broke it down into relevant function calls to make it easier to follow:

operator=(word_count.operator[]("a"), word_count.count("a") == 0 ? 1 : 2);
   ^       inserts element^                        ^reads same element
   |
assigns to element

If word_count["a"] does not exist, it was argued that it would be assigned to twice without a sequencing in between. I personally didn't see how that could happen if two things I thought were true actually were:

  1. When a side is picked to be evaluated, the whole side has to be evaluated before the other side can start.

  2. Constructs such as word_count["a"] = 1 exhibit well-defined behaviour, even in the case that an element is inserted and then assigned to.

Are these two statements true? Ultimately, is that actually undefined behaviour, and if it is, why does the second statement work (assuming it does)? If the second is false, I believe all the myMap[i]++;s in the world would be ill-formed.

Helpful Link: Undefined behavior and sequence points

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The behavior is unspecified, but not undefined.

Notice, that in the expression:

word_count["a"] = word_count.count("a") == 0 ? 1 : 2;
//              ^

The assignment operator marked with ^ is the built-in assignment operator, because std::map's operator [] returns a size_t&.

Per Paragraph 5.17/1 of the C++11 Standard on the built-in assignment operator(s):

The assignment operator (=) and the compound assignment operators all group right-to-left. [..] In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression. With respect to an indeterminately-sequenced function call, the operation of a compound assignment is a single evaluation.

This means that in a built-in assignment such as:

a = b

First the operands are evaluated (in unspecified order), then the assignment is performed, and finally the value computation of the whole assignment expression is performed.

Considering the original expression:

word_count["a"] = word_count.count("a") == 0 ? 1 : 2;
//              ^

Because of the paragraph quoted above, in no case there are two unsequenced assignments to the same object: the assignment marked with ^ will always be sequenced after the assignment performed by operator [] (as part of the evaluation of the left hand side expression) in case the key "a" is not present in the map.

However, the expression will have a different outcome based on which side of the assignment is evaluated first. Thus, the behavior is unspecified, but not undefined.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...