添加和初始化新的std :: map元素的最有效方法是什么?

时间:2019-01-08 23:26:18

标签: c++ stdvector stdmap

说,如果我有以下地图,其中每个元素都包含一个数组:

struct STRUCT{
    int value;
    std::vector<MY_DATA> myArr;
};

std::map<UINT, STRUCT> myMap;

然后,如果我想向该地图添加一个新元素并同时对其进行初始化:

//But, let's say we have a 'STRUCT' with a large number of items in the vector
std::vector<MY_DATA> arr;
arr.resize(0x10000);        //Arbitrary
int val = 123;

addToMap(&arr, val);

据我了解,我有以下几种实现方法:

void addToMap1(UINT id, std::vector<MY_DATA>* pArr, int val)
{
    //Method 1
    STRUCT myStruct;
    myStruct.myArr = *pArr;
    myStruct.value = val;
    myMap[id] = myStruct;
}

void addToMap2(UINT id, std::vector<MY_DATA>* pArr, int val)
{
    //Method 2
    myMap[id] = STRUCT();
    STRUCT* pS = &myMap[id];
    pS->myArr = *pArr;
    pS->value = val;
}

void addToMap3(UINT id, std::vector<MY_DATA>* pArr, int val)
{
    //Method 3
    myMap[id] = STRUCT();
    std::map<UINT, STRUCT>::iterator itr = myMap.find(id);
    STRUCT* pS = &itr->second;
    pS->myArr = *pArr;
    pS->value = val;
}

void addToMap4(UINT id, std::vector<MY_DATA>* pArr, int val)
{
    //Method 4
    std::pair<std::map<UINT, STRUCT>::iterator, bool> prNew = 
        myMap.insert(std::pair<UINT, STRUCT>(id, STRUCT()));
    ASSERT(prNew.second);       //It must have not existed before!  
    STRUCT* pS = &prNew.first->second;
    pS->myArr = *pArr;
    pS->value = val;
}

但是最有效的方法是什么?

2 个答案:

答案 0 :(得分:1)

如果您的意图是暗示覆盖地图中已经存在的键的现有数据,那么只需

void addToMap(UINT id, const std::vector<MY_DATA>* pArr, int val)
{
  STRUCT &pS = myMap[id];
  pS.value = val;
  pS.myArr = *pArr;
}

将非常有效地完成此操作。目前尚不清楚为什么您要在现有的“方法”中坚持首先将默认构造的STRUCT()保存到myMap[id]中。这完全没有必要。

其他优化机会包括:

  1. 从现有向量中移动数据,而不是复制它(如果可能)
  2. 甚至不构建源矢量,而直接在地图中构建目标矢量(如果可能)
  3. 如果源向量必须作为一个独立的对象存在(并且是长期存在的),那么可以将指向该向量的指针存储在地图中,而不是完整的副本

但是从您的描述中尚不清楚这是否适用于您的情况。


请注意,您不能为此目的使用emplace,因为emplace在这种情况下不会执行您想做的事情:它不会覆盖现有键的数据。在这种情况下,我们需要的是insert_or_assign的转发版本,但可惜它不存在。

答案 1 :(得分:0)

您可能会移动资源,例如:

void addToMap(UINT id, std::vector<MY_DATA>&& arr, int val)
{
    auto& s = myMap[id];
    s.myArr = std::move(arr);
    s.value = val;
}