• C++ map.insert 传参类型不同,构造/析构次数不同


    1. 传参方式

    使用 insert 为 map 插值时,insert 的传参包含以下几种可能:

    • make_pair 生成对象
    • pair(key_type, value_type) 生成对象
    • pair(const key_type, value_type) 生成对象
    • map<key_type, value_type>::value_type 生成对象

    不同的传参,导致不同次数的构造 / 析构函数调用。

    2. 测试代码与结果

    /*
    在 map 中不同的 insert 传参类型,导致的不同次数的构造/析构函数调用。
    */
    
    #include <iostream>
    #include <vector>
    #include <map>
    #include <string>
    
    using namespace std;
    
    class Data
    {
    public:
        Data(void)
        {
            cout << "Constructor" << endl;
        }
    
        Data(const Data& other)
        {
            cout << "Copy Constructor" << endl;
        }
    
        Data& operator=(const Data& other)
        {
            cout << "Assignment operator" << endl;
            return *this;
        }
    
        ~Data(void)
        {
            cout << "Destructor" << endl;
        }
    };
    
    class Tracker
    {
    public:
        Tracker(string name)
        {
            _name = name;
            cout << "### Testing " << name << endl;
        }
    
        ~Tracker(void)
        {
            cout << "### Done" << endl << endl;
        }
    
    private:
        string _name;
    };
    
    int main () {
        {
            Tracker tracker("insert data using make_pair");
            map<int, Data> c;
            Data d = Data();
            cout << "---- Begin ---- " << endl;
            c.insert(make_pair(1, d));
            cout << "----- End -----" << endl;
        }
    
        {
            Tracker tracker("insert data using pair<key_type, value_type>");
            map<int, Data> c;
            Data d = Data();
            cout << "---- Begin ---- " << endl;
            c.insert(pair<int, Data>(1, d));
            cout << "----- End -----" << endl;
        }
    
        {
            Tracker tracker("insert data using pair<const key_type, value_type>");
            map<int, Data> c;
            Data d = Data();
            cout << "---- Begin ---- " << endl;
            c.insert(pair<const int, Data>(1, d));
            cout << "----- End -----" << endl;
        }
    
        {
            Tracker tracker("insert data using map<key_type, value_type>::value_type");
            map<int, Data> c;
            Data d = Data();
            cout << "---- Begin ---- " << endl;
            c.insert(map<int, Data>::value_type(1, d));
            cout << "----- End -----" << endl;
        }
    
        return 0;
    }
    View Code

    3. 调用流程分析

    3.1 value_type 2 次 Copy Constructor 产生 1 个临时变量

    分解后的 value_type 调用细节对比图

    1. 构造 value_type 的临时变量,一次 Copy Constructor
    2. insert value_type 类型的参数,一次 Copy Constructor
    3. 析构 value_type 的临时变量,一次 Destructor

    3.2 pair(const key_type, value_type) 与 value_type 过程相同

    原因:value_type 的定义是: pair<const key_type,mapped_type> 

    参见:http://www.cplusplus.com/reference/map/map/

    3.3 pair(key_type, value_type)  3 次 Copy Constructor 产生 2 个临时变量

    根据下图的流程拆解可以看出,非 const 的 key_type 导致 insert 过程增加了一次 Copy Constructor

    3.4 make_pair 4 次 Copy Constructor 产生 3 个临时变量

    新增的一次 Copy Constructor 来自于 make_pair 过程。

    make_pair 的过程是:Constructs a pair object with its first element set to x and its second element set to y.

    伪代码如下:

    template <class T1,class T2>
      pair<T1,T2> make_pair (T1 x, T2 y)
      {
        return ( pair<T1,T2>(x,y) );
      }

    参见:http://www.cplusplus.com/reference/utility/make_pair/?kw=make_pair

    make_pair 时的 key 使用 const 变量,并未能减少 insert 阶段的一次 Copy Constructor

    const int k = 1;
    c.insert(make_pair(k, d));

    4. 结果分析

    1. insert 时,如果 key_type 不是 const 类型, 则增加一次 Copy Constructor
    2. make_pair 无法产生 const key_type 的 pair,导致 insert 增加一次 Copy Constructor
    3. map<key, value>::value_type 的 key 是 const 类型,使用简单,性能好。
  • 相关阅读:
    JVM字节码(七)
    JVM字节码(六)
    JVM字节码(五)
    JVM字节码(四)
    JVM字节码(三)
    JVM字节码(二)
    JVM字节码(一)
    JVM类加载器(五)
    JVM类加载器(四)
    php之 人员的权限管理
  • 原文地址:https://www.cnblogs.com/misspy/p/3865248.html
Copyright © 2020-2023  润新知