简体   繁体   中英

What is the most efficient way to add and initialize a new std::map element?

Say, if I have the following map, where each element contains an array:

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

std::map<UINT, STRUCT> myMap;

And then if I want to add a new element to that map and also initialize it at the same time:

//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);

From what I understand I have the following ways to do it:

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;
}

But what is the most efficient way to do it?

If your intent implies overwriting the existing data for the key that is already present in the map, then just plain

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

will do the trick quite efficiently. It is not clear why in your existing "methods" you insist on first saving a default-constructed STRUCT() into myMap[id] . This is completely unnecessary.

The other optimization opportunities would involve:

  1. Moving data from the existing vector instead of copying it (if possible)
  2. Not even constructing the source vector, and constructing the target vector directly in the map (if possible)
  3. It the source vector is required to exist as an independent object (and is long-lived), then a pointer to that vector can be stored in the map instead of a full copy

But it is not clear from your description whether this is applicable in your case.


Note that you cannot use emplace for this purpose since emplace does not do what you want to do in this case: it does not overwrite data for existing keys. What we'd need in this case is a forwarding version of insert_or_assign , but alas it does not exist.

You might move ressource, something like:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM