Home > Software design >  C set all pointers pointing to an object to null at once
C set all pointers pointing to an object to null at once

Time:09-11

while(condition){
    TConfig* curConfig = new TConfig();
    for( auto it : configMap)
    {
        itr->second = curConfig;
    }
}

if(condition)
    delete configMap[2];
    // set all elements equal to confidMap[2] to null

I need to make a map of pointers. Some elements in the map will be same. When I process one element I need all the same elements to be set to null. One option is to iterate over the map each time I process an element and set the elements to null. Can this be achieved in a more efficient way. Maybe by using shared Pointers.

CodePudding user response:

You can do this:

std::vector<std::unique_ptr<TConfig>> configs;
std::unordered_map<int, size_t> configMap; // value is index in configs

Now when you want to make a new config:

configMap[someKey1] = configs.size(); // capture index in configs
configMap[someKey2] = configs.size();
configs.emplace_back(new TConfig());

That is, you add as many entries as you want to configMap, each having the index of a new TConfig in the configs vector.

Now when you want to reset one of the TConfig pointers (destroying the config object), do this:

configs[configMap[2]].reset(); // instead of delete configMap[2];

That doesn't remove configMap[2], it simply resets the unique_ptr in configs. So now any other entries in configMap which pointed to the same pointer in configs will now be pointing to the null std::unique_ptr<TConfig>.

CodePudding user response:

The map value could be a pointer to a unique_ptr as in the example below demonstrating the operations of the question.

Notice that while this solution makes it relatively easy to use the map, the downside is that destructing the configMap with its unique_ptr pointers gets ugly. In a full solution, the configMap should be an object of a class where this destruction procedure is implemented in the destructor.

#include <iostream>
#include <map>
#include <set>
#include <memory>

struct TConfig  // Just an example "config" structure
{
   int a;
   // ...
};

int main()
{
    std::map<int, std::unique_ptr<TConfig> *> configMap;

    // Create new config inside a unique_ptr
    std::unique_ptr<TConfig> *curConfig = new std::unique_ptr<TConfig>(new TConfig{42});
    
    // Assign the new config to a couple of keys
    configMap[2] = curConfig;
    configMap[3] = curConfig;
    
    // Access the config via the map
    std::cout << "configMap[3] -> " << (*configMap[3])->a << std::endl;

    // Using the unique_ptr as a bool determines if its object is defined
    std::cout << "configMap[3] present: " << ((*configMap[3])?"yes":"no") << std::endl;
    
    // Deleting the config for any key ...
    configMap[2]->reset();
    
    // ... will invalidate it for all keys:
    std::cout << "configMap[3] present: " << ((*configMap[3])?"yes":"no") << std::endl;

    // Destructing configMap is cumbersome since each unique key must
    // be destructed only once.
    // This is accomplished by making a set of keys and destructing
    // each element of that set:
    std::set<std::unique_ptr<TConfig> *> configMapDestructor;
    for(auto it = configMap.begin(); it != configMap.end(); it  )
    {
        configMapDestructor.insert(it->second);
    }
    for(auto it = configMapDestructor.begin(); it != configMapDestructor.end(); it  )
    {
        delete *it;
    }

    return 0;
}
  • Related