Карта списка со структурами (содержащая список) — не может получить доступ к списку в структуре через карту

Я запустил поисковые системы, но не могу найти соответствующий ответ на мою проблему:

В принципе, я хочу иметь карту, каждая запись содержит список структур.
Сама структура содержит 2 std::string переменные и std::list<string>,

Все работает, как и ожидалось, несмотря на доступ к списку в структуре.

Один метод (здесь: getRules) создает запись карты, если необходимо, и прикрепляет к ней список и добавляет к ней один элемент struct (здесь: Rule).
В этом методе вызывается другой метод (здесь: getRuleParams), который должен позаботиться о добавлении элементов в список в структуре.

В методе getRuleParams список с добавленным элементом напрямую доступен через элемент struct.
В методе «sourrounding» список с добавленным элементом также напрямую доступен через элемент struct.

НО, если я хочу получить доступ к списку структуры или, что лучше, к ее элементам списка, то происходит странная вещь. Я понял, что адреса изменились (структура, список внутри структуры ….)

Вы можете видеть, что в выводе мой код производит (при условии, что он закодирован правильно).

Поскольку я новичок в C ++, возможно, мне не хватает чего-то очень простого / существенного.
Связано ли это с некоторыми конструкторами копирования, которые вызываются, но почему то же самое поведение только с использованием указателей на все «переменные»?

Я действительно надеюсь, что кто-то здесь может просветить меня.

Я упростил / изолировал свою проблему настолько, насколько мог. (Подписи методов должны быть такими, например, void*, потому что я полагаюсь на другие функции)

Пожалуйста, смотрите код ниже и спасибо заранее:

#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

Решение

Это серьезная проблема сама по себе:

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

Хотя я не советую эту модель, вы можете решить эту проблему следующим образом:

Rule rule = { target, action };
getRuleParams(&rule); // fill here, before the push

// then push.
(*policies).find(policy)->second.push_back(rule);

Но чтобы сделать это правильно, вы должны вставить пустое правило в список, а затем ссылку тот Правило объекта (тот, что в списке) для инициализации:

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

Если честно, самой парадигме нужно немного поработать, много лишнего find()Это происходит здесь, и методическое использование ссылок и итераторов может немного убрать это.


Пример переделки:

Следующее исключило все предложения вывода. Они действительно делали это Сильнее видеть проблемы. Пожалуйста, просмотрите следующее, чтобы, надеюсь, дать вам несколько идей:

#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's rule list...
for (RuleList::const_iterator rit = rules.begin(); rit != rules.end(); rit++)
{
cout << "Rule: " << policy << endl;

// for each rule in our curent rule's 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

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]