C++11初始化map

13

我尝试使用C++11语法来初始化STL map,但好像不起作用。在初始化之后,当我尝试访问元素时,它会尝试调用Foo的私有构造函数。我错过了什么吗?如果我使用at,它可以工作。我想知道是否可以使用operator[]来访问初始化的值...

#include <map>
#include <string>

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

private:
    Foo(){};
};


int main(){

    std::map<std::string, Foo> myMap = { {"1", Foo(10,5)}, {"2", Foo(5,10)} };
    int b  = myMap["1"].b;    // it tries to call private constructor of Foo.
    return 0;
}
2个回答

23
使用operator[]操作Map时,可以使用该操作符从Map中获取值或将值赋值给Map。为了将值赋值给Map,Map必须构造其值类型的对象,并通过引用返回它,以便您可以使用operator=覆盖现有对象。
因此,该类型必须是默认可构造的,以便可以创建一个新的对象进行赋值。
在运行时,如果键已经存在,则不会调用构造函数,但编译器无法知道是否会使用operator[]来访问不存在的值,因此需要将构造函数声明为public。

20

mapoperator[]要求类型是具有默认构造函数的,因为它会在不存在时创建一个新条目。

你可以使用at()代替operator[],如果该条目不存在,则会抛出异常:

int b  = myMap.at("1").b;

需要构造函数存在并不意味着如果对象已经存在就应该调用它,而事实上不应该这样做。 - David Rodríguez - dribeas
6
@David:C++11确实对map<>::operator[](§23.4.4.3/2,6)要求“具有默认构造函数”(DefaultConstructible concept)。 - ildjarn
确实如此...我当时没有想清楚,读取到构造函数实际上被调用了。 - David Rodríguez - dribeas
理论上,你可以有一个const operator [],并在没有默认构造函数的情况下SFINAE掉非const版本。不过这可能会非常令人困惑;新的at()显然是更好的解决方案。 - JohannesD
@JohannesD 可能吧。我认为那是一个有趣的想法。 - R. Martinho Fernandes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接