Question

I recently ran into an interesting bug with a program at work. I would like to know a little bit more about how operator[] works with maps. Consider the following example code:

#include <map>
#include <iostream>
#include <utility>
#include <tuple>

class test
{
    public:
    test(int a, char b) {
        a_ = a;
        b_ = b;
    }

    void print() {
       std::cout << a_ << " " << b_ << std::endl;
    }

    private:
       int a_;
       char b_;
 };  


int main()
{
    std::map<int, test> mapper;
    mapper.emplace(std::piecewise_construct,
            std::forward_as_tuple<int>(1),
            std::forward_as_tuple<int, char, double>(1, 'c', 2.34));
    mapper[1].print();
}

The code is very simple, and the objective is pretty clear, I dont want to have a default constructor for the class test. This code wont compile however, because mapper[1].print() calls the default constructor.

The obvious solution here is to replace mapper[1].print() with mapper.find(1)->second.print(). I am just interested in why it is necessary for mapper[1] to create a test. Does this mean that every time in any code i have written with a map using operator[] that it creates a default and copies the class before calling its functions?

This seems like a huge waste of time, i understand its necessity during something like this: mapper[2] = test(1, 'a'). Is there not any way that it could tell that its not part of an operator= call? I guess not.

Was it helpful?

Solution

from Visual Studio 2012 library

mapped_type& operator[](key_type&& _Keyval)
    {   // find element matching _Keyval or insert with default mapped
    iterator _Where = this->lower_bound(_Keyval);
    if (_Where == this->end()
        || this->_Getcomp()(_Keyval, this->_Key(_Where._Mynode())))
        _Where = this->insert(_Where,
            pair<key_type, mapped_type>(
                _STD move(_Keyval),
                mapped_type()));  // <---- call to default constructor
    return (_Where->second);
    }

as you can see it require mapped_type to be default construable to compile doesn't means it need to construct the object every time you call operator[]

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top