我了解到 运算符(operator)[] 相当于
(*((this->insert(make_pair(k,mapped_type()))).first)).second
因此,如果 map 中不存在键,请使用 运算符(operator)[] 效率低于使用 插入 , 对?因为还有一步,默认构造。所以我写了一个demo来测试,像这样。
#include <iostream>
#include <map>
using namespace std;
static int id = 0;
class Foo
{
public:
Foo()
: _val(0)
{
_id = ++id;
cout << _id << " construct_no_param:" << _val << endl;
}
Foo(int val)
: _val(val)
{
_id = ++id;
cout << _id << " construct_has_param:" << _val << endl;
}
Foo(Foo &rhs)
: _val(rhs._val)
{
_id = ++id;
cout << _id << " construct_copy:" << _val << endl;
}
Foo(const Foo &rhs)
: _val(rhs._val)
{
_id = ++id;
cout << _id << " construct_const_copy:" << _val << endl;
}
Foo &operator=(Foo &rhs)
{
_val = rhs._val;
cout << _id << " assign:" << _val << endl;
}
Foo &operator=(const Foo &rhs)
{
_val = rhs._val;
cout << _id << " const_assign:" << _val << endl;
}
~Foo()
{
cout << _id << " destruct:" << _val << endl;
}
int _val;
int _id;
};
int main() {
map<int, Foo> m;
const Foo f(2);
cout << "-----" << endl;
// m[1] = f;
// m.insert(make_pair(1, f));
cout << "-----" << endl;
return 0;
}
首先,我使用了 运算符(operator)[] m[1] = f;
我得到了这个:1 construct_has_param:2
-----
2 construct_no_param:0
3 construct_const_copy:0
4 construct_const_copy:0
3 destruct:0
2 destruct:0
4 assign:2
-----
1 destruct:2
4 destruct:2
然后,我用了 插入 m.insert(make_pair(1, f));
我得到了这个:1 construct_has_param:2
-----
2 construct_const_copy:2
3 construct_const_copy:2
4 construct_const_copy:2
5 construct_const_copy:2
4 destruct:2
3 destruct:2
2 destruct:2
-----
1 destruct:2
5 destruct:2
结果与我的预期不符。为什么insert
有更多的建筑吗?这里发生了什么?顺便说一句,我使用 -O0 选项来禁用优化,但我不确定它是否有效。
gcc 版本 4.8.2 20131212 (Red Hat 4.8.2-8) (GCC)
最佳答案
表达式 make_pair(1, f)
有类型 std::pair<int, Foo>
,这不是您的 map value_type
, 即 std::pair<const int, Foo>
,所以 insert
的参数中有一个拷贝.然后在 map
中有 2 个拷贝,如果你的所有特殊成员没有抑制移动构造的生成,那将是移动。
如果您想尽可能避免复制,请使用 emplace
m.emplace(1, f);
并定义 Foo
的移动构造函数和赋值Foo(Foo &&rhs)
: _val(std::exchange(rhs.val, 0))
{
_id = ++id;
cout << _id << " move:" << _val << endl;
}
Foo& opeator=(Foo &&rhs)
{
std::swap(_val, rhs._val);
cout << _id << " move assign:" << _val << endl;
}
我还建议删除非常量复制操作。
关于c++ - std::map::operator[] 比 std::map::insert 更有效吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64042174/