C++带有地图的程序 - 解释下面的程序是如何工作的

C++ program with map - Explain the below program how it's working

本文关键字:程序 何工作 工作 地图 C++ 解释      更新时间:2023-10-16

在下面的程序中,tmp_data首先打印为:"Ravindra Kumar"。但是在复制到地图后,它被更改为"RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR当我们下次打印时,它仍然打印"Ravindra Kumar" - 如何。它应该打印RRRRRRRRRRRRRR对吗?

#include <iostream>
#include <cstring>
#include <string>
#include <map>
using namespace std;
void fun_call( );
main(){
        cout << "printing all data " << endl ;
        fun_call();
        fun_call();
}
void fun_call()
{
      //  static void *tmp_data;
        void *tmp_data;
        char *str="Ravindra Kumar";
        char *str1="RRRRRRRRRRRRRRRRRRRRR";
        char name[]="Ravi";
        char value[100];
        static std::map<std::string,void *> name_data_map;
        std::map<std::string,void *>::iterator iter   ;
        iter=name_data_map.find(name) ;
        if ( iter == name_data_map.end())
        {
        tmp_data = (void *) malloc ( strlen(str)+1 );
        memcpy(tmp_data,str,strlen(str)+1);
        name_data_map[name]=tmp_data;
        cout << "Inside the if" << endl ;
        }
        cout << "Outside the if" << endl ;
        iter=name_data_map.find(name) ;
        memcpy(value,iter->second,strlen(str)+1);
        cout << "value is " << value <<  endl ;
        tmp_data=(void *)malloc(100000);
        memcpy(tmp_data,str1,strlen(str1)+1);
}

输出:

$ ./a.out
printing all data
Inside the if
Outside the if
value is Ravindra Kumar
Outside the if
value is Ravindra Kumar

您将"RRRRRRRRRRRRRRRRRRRRR"复制到 tmp_data 中,然后退出该函数,完全丢弃tmp_data(顺便说一句,没有释放它,所以你那里有内存泄漏)。下一次调用 fun_call 将创建一个新的 tmp_data 局部变量,其值与您之前设置的值无关。但是,name_data_map被声明为 static ,因此它只分配一次(在第一次调用 fun_call 时),然后重用,保留您在上一次调用中放入的值(该值实际上是与您稍后将 R 复制到其中的内存块不同的内存块)。

更新 - 更详细的解释

这里

    tmp_data = (void *) malloc ( strlen(str)+1 );
    memcpy(tmp_data,str,strlen(str)+1);
    name_data_map[name]=tmp_data;

你分配一个内存块,将"Ravindra Kumar"复制到其中,并在地图中存储指向它的指针。此时,name_data_map[name]tmp_data指向同一内存块。从图形上看,它可能大致如下所示(为了简单起见,假设两个文本文本连续存储在内存中,这在现实生活中可能是也可能不是):

name_data_map[name] ----
                        ˇ
tmp_data ---------------
                        ˇ
raw memory    ..........Ravindra KumarRRRRRRRRRRRRRRRRRRRRR............

如果您修改了该内存块的内容(例如,通过将不同的文本复制到tmp_data中),则更改也将通过name_data_map[name]可见,因为它们都指向相同的内存位置。

但是,反之亦然:更改地图值后,例如

    name_data_map[name]=str1;

程序状态如下所示:

name_data_map[name] --------------------
                                        ˇ
tmp_data ---------------
                        ˇ
raw memory    ..........Ravindra KumarRRRRRRRRRRRRRRRRRRRRR............

使两个指针指向不同的位置,因此一个指针的更改不会影响另一个指针。因此,请注意,更改指针的值与更改指针指向的内存值之间存在根本区别。

你完全在几行之后做前者,只是用tmp_data

    tmp_data=(void *)malloc(100000);
    memcpy(tmp_data,str1,strlen(str1)+1);

第一行改变了tmp_data的值,所以现在它不再指向与name_data_map[name]相同的位置!之后,无论您对新分配的内存块做什么,它都不会再影响name_data_map[name]。这就是您未能更改它的原因。

如果我们声明地图为非静态,那么我们可以更改它吗?

错。声明地图static对此没有影响 - 它只会影响地图的范围。当你退出fun_call时,非静态映射将不复存在,丢失存储在其中的所有值。当它活着时,您可以更改其值,无论它是否static。您只需要使用正确的指针即可。

如果您的目标是通过 tmp_data 更改存储在映射中的值,只需删除第二个malloc并修改第一个以分配更长的块(因为str1str 长,因此尝试将str1复制到长度为 str 的缓冲区中会导致缓冲区溢出, 即未定义的行为)。之后,您应该有一个有效的 - 虽然令人讨厌 - 代码,因为尝试"背后"修改映射中的值通常不是一个好主意。此外,在C++代码中混合使用C结构(malloc和原始指针,尤其是void*)是一个坏主意。如果您只是在试验,这是可以接受的 - 机器人请不要在生产代码中这样做。您的意图有所不同,请澄清。

以下代码更简单,似乎可以执行您想要的操作。 有什么理由更喜欢 char* 而不是 std::string 作为映射中的值吗?

#include <iostream>
#include <string>
#include <map>
void fun_call()
{
        const char* str="Ravindra Kumar";
        const char* str1="RRRRRRRRRRRRRRRRRRRRR";
        const char* name="Ravi";
        static std::map<std::string,std::string> name_data_map;
        std::map<std::string,std::string>::iterator iter;
        iter=name_data_map.find(name) ;
        if ( iter == name_data_map.end())
        {
          name_data_map[name]=str;
          cout << "Inside the if" << endl ;
        }
        cout << "Outside the if" << endl ;
        iter=name_data_map.find(name) ;
        cout << "value is " << iter->second <<  endl ;
        iter->second = str1;
}
main(){
        cout << "printing all data " << endl ;
        fun_call();
        fun_call();
}

输出:

printing all data 
Inside the if
Outside the if
value is Ravindra Kumar
Outside the if
value is RRRRRRRRRRRRRRRRRRRRR