Why is the implementation of vector :: operator [] not the same as map :: operator []?

Is there any reason for std::vector operator[] simply return the link instead of inserting a new element? The cppreference.com page for vector::operator says here

Unlike std::map::operator[] , this operator never inserts a new element into the container.

While the map::operator[] page says

"Returns a reference to a value that maps to a key equivalent to a key, pasting if that key does not already exist."

Why it was not possible to execute vector::operator[] by calling vector::push_back or vector::insert , for example, how map::operator[] calls insert(std::make_pair(key, T())).first->second; ?

+5
source share
3 answers

Quite simple: because it makes no sense. What do you expect

 std::vector<int> a = {1, 2, 3}; a[10] = 4; 

make? Create fourth element even if you specify index 10? Create items 3 through 10 and return the link to the last? None of them would be particularly intuitive.

If you really want to fill the vector with operator[] values ​​instead of push_back , you can call resize vector to create the elements before setting them.

Edit: Or, if you really want to have an associative container, where the index is important separately from the order, std::map<int, YourData> might make sense.

+7
source

Display and vector are completely different concepts. A map is an "associative container," while a vector is an "sequence container." Differentiation of differences is beyond the scope of this answer, although at the most superficial level the map is usually implemented as a red-black tree, and the vector is a curled shell over the C-style array (elements stored adjacent to the Memory).

If you want to check if an element exists, you need to resize the entire container. But what happens if you decide to remove an item? What do you do with the recordings you just created? With card:

 std::map<int, int> m; m[1] = 1; m.erase(m.begin()); 

This is an ongoing operation.

With vector:

 std::vector<int> v; // ... initialize some values between 25 and 100 v[100] = 1; v.erase(v.begin() + 25, v.end()); 

This is a linear operation. This is terribly inefficient (comparative) with the card. Although this is a contrived example, it is not hard to imagine how this could explode in other scenarios. At a minimum, most people will try to avoid operator[] , which is like the cost itself (maintenance and code complexity).

+1
source

Is there a reason for the std :: vector [] operator to simply return a link instead of inserting a new element?

std::vector::operator[] is implemented as an array, since std::vector is a sequence container (that is, similar to an array). Standard arrays for integral types cannot be accessed outside boundaries. Similarly, access to std::vector::operator[] with an index outside the length of the vector is also not allowed. So yes, the reasons why it is not implemented, as you ask, because in a different context, arrays in C ++ do not work like that.

std::map::operator[] not a container of the sequence. Its syntax makes it look like associative arrays in other languages. As for C ++ (and its predecessor, C), map::operator[] is just syntactic sugar. This is the "black sheep" of the operator[] family, not std::vector::operator[] .

An interesting part of the C ++ specification is that accessing a map with a key that does not exist, using std::map::operator[] adds an element to the map. In this way,

 #include <iostream> #include <map> int main(void) { std::map<char, int> m; m['a'] = 1; std::cout << "m['a'] == " << m['a'] << ", m.size() == " << m.size() << std::endl; std::cout << "m['b'] == " << m['b'] << ", m.size() == " << m.size() << std::endl; } 

leads to:

 m['a'] == 1, m.size() == 1 m['b'] == 0, m.size() == 2 

See also: Difference between map [] and map.at in C ++? :

[ map::at ] throws an exception if the key does not exist, find returns aMap.end() if the element does not exist, and the operator[] value initializes a new value for the corresponding key if the value does not exist.

0
source

All Articles