c++ - std::map::operator[] 比 std::map::insert 更有效吗?

标签 c++ stl

我了解到 运算符(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/

相关文章:

c++ - 在 C++ 中按值删除元素 - 首选成语真的由双重否定组成吗?

c++ - 抛出和共享对象的可见性

c++ - STL-Like 范围,如果我这样做会出什么问题?

c++ - auto_ptr 和 unique_ptr 有什么意义?

c++ - 如何在 gnu/linux 上安装 boost

c++ - 在 NodeJS 中将 Raw 流转换为 Wav 流

c++ - 使用结构对象

c++ - 使用 lower_bound、upper_bound 和 binary_search 查找具有相等成员字段的对象

c++ - 使用 STL 列出特定子集

c++ - 使用 STL 和一元函数适配仿函数检查列表成员资格