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