List map with structs (containing the list) - cannot access the list inside the struct via the map

I started search engines, but I can not find the appropriate answer to my problem:

Basically, I want to have a map, each entry contains a list of structures. The structure itself contains 2 std::string variables and a std::list<string> .

Everything works as expected, despite accessing the list inside the structure.

One method (here: getRules), if necessary, creates a map record and appends a list to it and adds one structure element to it (here: Rule). As part of this method, another method is called (here: getRuleParams), which should take care of adding items to the list inside the structure.

In the getRuleParams method, the list with the added element is directly accessible through the structure element. In the sourrounding method, a list with an added element is also available directly through the structure element.

BUT , if I want to access the list of structures, or, better, list the elements, then something strange will happen. I realized that the addresses have changed (struct, list inside struct ....)

You can see that in the output that my code produces (if it is correctly encoded).

Since I'm new to C ++, maybe I am missing something very light / substantial. This is due to some copy constructors that are called, but why is it the same behavior using pointers to all "variables"?

I really hope someone here can enlighten me.

I simplified / isolated my problem as much as I could. (Method signatures should be this way, for example, void* , because I rely on other functions)

Please see the code below and thanks in advance:

 #include <list> #include <map> #include <string> #include <iostream> using namespace std; struct Rule { string target; string action; list<string> params; }; static int getRuleParams(void *prule) { Rule* rule = (Rule*) (prule); string param = "Entry!"; //Fill struct with ruleparams rule->params.push_back(param); cout << "Method getRuleParams()\n" << "parameter: " << *(rule->params.begin()) << " \nadress of rule:\t\t\t" << rule << " \nadress of rule.params:\t\t" << &(rule->params) << std::endl << std::endl; return 0; } static int getRules(void *dbpolicies) { string policy = "FileIO"; string target = "TARGET"; string action = "DENY"; std::map<std::string, std::list<Rule> >* policies = (std::map<std::string, std::list<Rule> >*) (dbpolicies); //Create std::list<DBRule> (list) for Policy Map-Entry, if not existing if ((*policies).find(policy) == (*policies).end()) (*policies)[policy] = std::list<Rule>(); //Fill struct Rule rule = { target, action }; (*policies).find(policy)->second.push_back(rule); //call Method which manipulates params in struct getRuleParams(&rule); cout << "Method getRulesforPackage() (access rule directly):"; cout << "\nparameter = " << *(rule.params.begin()) << "\naddress of rule:\t\t" << &rule; cout << "\nadress of rule.params:\t\t" << &(rule.params) << std::endl << std::endl; cout << "Method getRulesforPackage() access rule via map:" << std::endl; //READ params from map entry -> EVIL std::list<Rule> dbrules = (*policies).find(policy)->second; Rule firstrule = *dbrules.begin(); std::list<std::string> dbruleparams = firstrule.params; string ruleparam = *(firstrule.params.begin()); //EVIL! // string ruleparam = *(dbruleparams.begin()); // <- REALLY EVIL! (program crashes) //Variant 2: pointers only std::list<Rule>* dbrules2 = &(*policies).find(policy)->second; Rule* firstrule2 = &*(dbrules2->begin()); std::list<std::string>* dbruleparams2 = &(firstrule2->params); cout << "rule.target = " << firstrule.target << "\nrule.action = " << firstrule.action << std::endl; cout << "address of rule:\t\t" << &firstrule << std::endl; cout << "address of rule (pointer):\t" << firstrule2 << std::endl; // string ruleparam2 = *(dbruleparams2->begin()); //REALLY EVIL! (program crashes) // cout << "parameter: " << ruleparam << std::endl; // cout << "parameter (pointer): " << ruleparam2 << std::endl; return 0; } static std::map<std::string, std::list<Rule> > getPolicies() { std::map<std::string, std::list<Rule> > policies; getRules(&policies); return policies; } int main() { std::map<std::string, std::list<Rule> > policies = getPolicies(); } 
+4
source share
1 answer

This is an important issue in itself:

 Rule rule = { target, action }; (*policies).find(policy)->second.push_back(rule); //call Method which manipulates params in struct // **NOTE**: Fills the local variable "rule", not the one just pushed into the list getRuleParams(&rule); 

Although I do not necessarily recommend this model, you can probably solve this problem:

 Rule rule = { target, action }; getRuleParams(&rule); // fill here, before the push // then push. (*policies).find(policy)->second.push_back(rule); 

But for proper operation, you must click on an empty rule in the list, and then refer to this rule object (the one in the list) to initialize:

 Rule rule = { target, action }; (*policies)[policy].push_back(rule); getRuleParams(&(*policies)[policy].back()); 

Honestly, the paradigm itself needs a little work, there is a lot of unnecessary find() ing here, and methodical use of links and iterators can clean this up a bit.


Rework example:

Listed below are all weekend offers. In fact, it was more difficult for them to see the problems. Please read the following to hopefully give you some ideas:

 #include <list> #include <map> #include <string> #include <iostream> using namespace std; // basic rule with strin parameter list typedef std::list<std::string> ParamList; struct Rule { string target; string action; ParamList params; }; typedef std::list<Rule> RuleList; typedef std::map<std::string, RuleList> MapStringToRuleList; static int getRuleParams(void *prule) { Rule* rule = (Rule*) (prule); rule->params.push_back("Entry!"); return 0; } static int getRules(void *dbpolicies) { string policy = "FileIO"; string target = "TARGET"; string action = "DENY"; MapStringToRuleList* policies = (MapStringToRuleList*)(dbpolicies); // push a new rule into the list. Rule rule = {target, action}; RuleList& rules = (*policies)[ policy ]; rules.push_back(rule); //call Method which manipulates params in struct getRuleParams(&rules.back()); // for each rule in our policy rule list... for (RuleList::const_iterator rit = rules.begin(); rit != rules.end(); rit++) { cout << "Rule: " << policy << endl; // for each rule in our curent rule params list const ParamList& params = rit->params; for (ParamList::const_iterator pit = params.begin(); pit != params.end(); pit++) { cout << " Rule Param: " << *pit << endl; // TODO: use current param for something. } } return 0; } static MapStringToRuleList getPolicies() { MapStringToRuleList policies; getRules(&policies); return policies; } int main() { MapStringToRuleList policies = getPolicies(); } 
+3
source

All Articles