当您不想要默认构造函数时,map operator []的安全性

时间:2014-05-06 02:11:51

标签: c++ map default-constructor

我最近遇到了一个有趣的工作程序错误。我想更多地了解operator[]如何使用地图。请考虑以下示例代码:

#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();
}

代码非常简单,目标非常明确,我不想为类测试提供默认构造函数。但是,此代码无法编译,因为mapper[1].print()调用默认构造函数。

这里显而易见的解决方案是将mapper[1].print()替换为mapper.find(1)->second.print()。我只是感兴趣为什么mapper [1]需要创建test。这是否意味着每次使用operator[]使用地图编写的任何代码都会创建默认值并在调用其函数之前复制该类?

这似乎是浪费时间,我理解它在这样的事情中的必要性:mapper[2] = test(1, 'a')。是否有任何方式可以说它不是operator=电话的一部分?我猜不会。

1 个答案:

答案 0 :(得分:3)

来自Visual Studio 2012库

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);
    }

正如您所看到的那样,mapped_type需要operator[]作为默认构造才能编译并不意味着每次调用{{1}}

时都需要构造对象