Доступ к элементу карты с помощью указателя в C

#c

Вопрос:

Я недавно перешел с c на c и просто не могу понять, что я здесь делаю не так. Я хотел бы получить доступ и установить элемент карты с помощью другой функции.

Вот мой пример, который вы можете просто скопировать в cpp.sh или так, если хотите

 #include lt;iostreamgt; #include lt;mapgt;  using namespace std;  struct test{  int i;  int j; };    void addValues(test* val){    if (val == NULL){  val = new test();  coutlt;lt;"new";  }  val-gt;i = 10;  val-gt;j = 12; }  void printVal(test* val){  coutlt;lt;"finish " lt;lt; val-gt;i lt;lt; " " lt;lt; val-gt;j; }  int main() {    maplt;string, test*gt; bla = {{"test1",NULL}};    addValues(bla.at("test1"));    printVal(bla.at("test1"));   return 0; }  

код из моего проекта немного сложнее, но в основном это проблема. Я создал тест в addValues() и не удалил его. Почему я не могу напечатать это значение в printVal()? Что я упускаю?

Заранее спасибо!

Комментарии:

1. По той же причине, которая val = malloc(sizeof(test)); не будет работать в C. Указатели передаются по значению, вам необходимо передавать по ссылке, если вы хотите, чтобы изменения переменной были видны вне функции

2. Что ж, в более современном C даже использование new/delete больше не рекомендуется. А для строк есть std::строка. Вскоре я покажу небольшой пример

3. std::map здесь это не имеет значения, test* t = nullptr; addValues(t); приведет к той же проблеме.

4. Вы говорите, что отображаете «элемент с помощью указателя» в своем вопросе. Но ваш код нигде не содержит указателя на элемент карты. Ты имел в виду maplt;string, testgt; и нет maplt;string, test*gt; ?

Ответ №1:

Параметры передаются по значению. Указатели не являются исключением из этого правила. Вы addValues изменяете локальную копию указателя при nullptr передаче a. Изменение этой локальной копии не влияет на указатель на карте. Передайте указатель по ссылке:

 void addValues(test*amp; val){    if (val == nullptr){  val = new test();  coutlt;lt;"new";  }  val-gt;i = 10;  val-gt;j = 12; }  

Или еще лучше, не используйте необработанные указатели в первую очередь. Кроме того, подумайте о том, чтобы написать конструктор, который инициализирует члены test вместо того, чтобы полагаться на вызывающего для их инициализации.

Ответ №2:

Пример :

 #include lt;iostreamgt; #include lt;mapgt;  //using namespace std; NO teach yourself not to do this.  struct test  {  int i = 0; // lt;== in c   you can initialize values of structs  int j = 0; };  // this instead of printVal std::ostreamamp; operatorlt;lt;(std::ostreamamp; os, const testamp; t) {  os lt;lt; "i = " lt;lt; t.i lt;lt; ", j = " lt;lt; t.j lt;lt; "n";  return os; }  int main() {  std::maplt;std::string, testgt; map =  {  {"test1",{1,1}},  {"test2",{2,2}},  };   // loop over all entries in the map  // range based for loop.   // each entry in the map is a key,value pair (not they key, not the value but a pair)  // https://en.cppreference.com/w/cpp/language/range-for   std::cout lt;lt; "range based for over keyvalue pairsn";  for (const autoamp; kv : map)  {  // note kv.second is where we use operatorlt;lt; from earlier.  std::cout lt;lt; "Key : " lt;lt; kv.first lt;lt; ", value : " lt;lt; kv.second lt;lt; "n";  }  std::cout lt;lt; "n";   // structured bindings make code more readable  // https://en.cppreference.com/w/cpp/language/structured_binding  std::cout lt;lt; "range based for using structured bindings n";  for (const autoamp; [key, value] : map)  {  std::cout lt;lt; "Key : " lt;lt; key lt;lt; ", value : " lt;lt; value lt;lt;"n";  }  std::cout lt;lt; "n";     return 0; }