我试图理解并确保将元素插入std::map
的三种不同方式实际上是相同的。
std::map<int, char> mymap;
在声明了mymap
之后,这三个方法是否会为键a
插入一个值为10
的元素?
mymap[10]='a';
mymap.insert(mymap.end(), std::make_pair(10, 'a'));
mymap.insert(std::make_pair(10, 'a'));
特别是,当mymap.end()
中没有现有元素时,使用std::map
有意义吗?
答案 0 :(得分:4)
主要区别在于,(1)首先是在地图中默认构造key
对象,以便能够返回对该对象的引用。这使您可以为其分配一些内容。
如果要使用存储在地图中但没有默认构造函数的类型,请记住这一点。示例:
struct A {
explicit A(int) {};
};
std::map<int, A> m;
m[10] = A(42); // Error! A has no default ctor
m.insert(std::make_pair(10, A(42))); // Ok
m.insert(m.end(), std::make_pair(10, A(42))); // Ok
另一个显着区别是(如@PeteBecker在评论中指出的)(1)会覆盖地图中的现有条目,而(2)和(3)不。
答案 1 :(得分:1)
是的,它们实际上是相同的。在声明mymap
之后,这三种方法都将mymap
变成{10, 'a'}
。
当mymap.end()
中没有现有元素时,可以使用std::map
。在这种情况下,begin() == end()
是表示空容器的通用方式。
答案 2 :(得分:1)
(1)与(2)和(3)不同。 (1)将替换元素,其中(2)和(3)将失败并且返回值表示未发生插入。
(1)还要求映射类型是默认可构造的。实际上(1),第一个默认值将构造该对象(如果尚不存在)并将其替换为指定的值。
(2)和(3)也不同。要了解差异,我们需要了解(2)中的迭代器的作用。从cppreference开始,迭代器指向一个提示,在该提示中,插入应尽可能地靠近该提示。根据提示的有效性,会有性能差异。从同一页面引用:
如果插入发生在提示之后的位置,则为摊销常数,否则为容器大小的对数。(直到C ++ 11)
如果插入发生在提示之前的位置,则为摊销常数,否则为容器大小的对数。 (自C ++ 11起)
因此,对于大型地图,如果我们已经知道位置的话,我们可以提高性能。
所有这些都已经讲完了,如果您刚刚创建地图,并且您按照问题中的说明在地图中没有任何先行元素的情况下进行操作,那么我想说这三者实际上将是相同的(尽管存在内部操作将与上面指定的不同)。