• 为什么C++ map容器emplace()、emplace_hint()的执行效率比insert()高?

    上一节在学习 C++STL map 容器的 emplace() 和 emplace_hint() 的基本用法时,还遗留了一个问题,即为什么 emplace() 和 emplace_hint() 的执行效率会比 insert() 高?

    原因很简单,它们向 map 容器插入键值对时,底层的实现方式不同:

    • 使用 insert() 向 map 容器中插入键值对的过程是,先创建该键值对,然后再将该键值对复制或者移动到 map 容器中的指定位置;
    • 使用 emplace() 或 emplace_hint() 插入键值对的过程是,直接在 map 容器中的指定位置构造该键值对。

    也就是说,向 map 容器中插入键值对时,emplace() 和 emplace_hint() 方法都省略了移动键值对的过程,因此执行效率更高。下面程序提供了有利的证明:

    #include <iostream>
    #include <map>  //map
    #include <string> //string
    using namespace std;
    
    class testDemo
    {
    public:
        testDemo(int num) :num(num) {
            std::cout << "调用构造函数" << endl;
        }
        testDemo(const testDemo& other) :num(other.num) {
            std::cout << "调用拷贝构造函数" << endl;
        }
        testDemo(testDemo&& other) :num(other.num) {
            std::cout << "调用移动构造函数" << endl;
        }
    private:
        int num;
    };
    
    int main()
    {
        //创建空 map 容器
        std::map<std::string, testDemo>mymap;
    
        cout << "insert():" << endl;
        mymap.insert({ "http://c.biancheng.net/stl/", testDemo(1) });
       
        cout << "emplace():" << endl;
        mymap.emplace( "http://c.biancheng.net/stl/:", 1);
    
        cout << "emplace_hint():" << endl;
        mymap.emplace_hint(mymap.begin(), "http://c.biancheng.net/stl/", 1);
        return 0;
    }

    程序输出结果为:

    insert():
    调用构造函数
    调用移动构造函数
    调用移动构造函数
    emplace():
    调用构造函数
    emplace_hint():
    调用构造函数

    分析一下这个程序。首先,我们创建了一个存储 <string,tempDemo> 类型键值对的空 map 容器,接下来分别用 insert()、emplace() 和 emplace_hint() 方法向该 map 容器中插入相同的键值对。

    从输出结果可以看出,在使用 insert() 方法向 map 容器插入键值对时,整个插入过程调用了 1 次 tempDemo 类的构造函数,同时还调用了 2 次移动构造函数。实际上,程序第 28 行代码底层的执行过程,可以分解为以下 3 步:

    //构造类对象
    testDemo val = testDemo(1); //调用 1 次构造函数
    //构造键值对
    auto pai = make_pair("http://c.biancheng.net/stl/", val); //调用 1 次移动构造函数
    //完成插入操作
    mymap.insert(pai); //调用 1 次移动构造函数

    而完成同样的插入操作,emplace() 和 emplace_hint() 方法都只调用了 1 次构造函数,这足以证明,这 2 个方法是在 map 容器内部直接构造的键值对。

    因此,在实现向 map 容器中插入键值对时,应优先考虑使用 emplace() 或者 emplace_hint()。

更多...

加载中...