C ++程序与地图 - 解释下面的程序如何工作 [英] C++ program with map - Explain the below program how it's working

查看:115
本文介绍了C ++程序与地图 - 解释下面的程序如何工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的程序中,tmp_data首先打印为:Ravindra Kumar。但是,在复制到地图后,更改为RRRRRRRRRRR。当我们下次打印时,它仍然打印Ravindra Kumar - 如何。假设要打印RRRRRRRR?

  #include< iostream> 
#include< cstring>
#include< string>
#include< map>
使用命名空间std;

void fun_call();
main(){
cout<<< 打印所有数据<<终点

fun_call();
fun_call();

}

void fun_call()
{
// static void * tmp_data;
void * tmp_data;
char * str =Ravindra Kumar;
char * str1 =RRRRRRRRRRRRRRRRRRRR;
char name [] =Ravi;
char值[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<<< if内<终点
}
cout<<< 在if之外<终点
iter = name_data_map.find(name);

memcpy(value,iter-> second,strlen(str)+1);
cout<<< 值为<<值<<终点
tmp_data =(void *)malloc(100000);
memcpy(tmp_data,str1,strlen(str1)+1);

}

输出:

  $ ./a.out 
打印所有数据
如果
里面如果
值之外是Ravindra Kumar
如果
值是Ravindra Kumar


解决方案

您将RRRRRRRRRRRRRRRRRRRR复制到 tmp_data 中,然后退出该功能,丢弃 tmp_data总共(btw没有释放它,所以你有一个内存泄漏)。下一次调用 fun_call 将创建一个新的 tmp_data 局部变量,其值与您之前设置的值无关至。但是, name_data_map 被声明为 static ,所以它只被分配一次(在第一次调用 fun_call ),然后重新使用,保留在上一次调用中放入的值(该值实际上与将R复制到稍后的内存块不同)。 p>

更新 - 更详细的说明



这里

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

原始内存.......... Ravindra Kumar\RRRRRRRRRRRRRRRRRRRRR\0 ............

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



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

 code> name_data_map [name] = str1; 

程序状态如下所示:

  name_data_map [name] -------------------- 

tmp_data ----- ----------

原始内存.......... Ravindra Kumar\R0RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\0 ...........

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



你完全是前几行,只是用 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 并修改第一个分配一个更长的块(因为 str1 更长比 str ,所以尝试将 str1 复制到长度为 str 导致缓冲区溢出,即未定义的行为)。之后,你应该有一个工作 - 尽管令人讨厌的代码,因为它通常不是一个好主意,尝试和修改地图背后的价值观。此外,在C ++代码中混合C构造( malloc 和原始指针,特别是 void * )是一个坏主意。如果你只是试验,这是可以接受的 - 机器人,请不要在生产代码中做到这一点。你的意图不一样,请澄清。


In the below program, tmp_data is printing first as : "Ravindra Kumar". But after copying into the map it's changed to "RRRRRRRRRRR". When we print next time, it's still printing "Ravindra Kumar" - how. It suppose to print RRRRRRRR right ?

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

}

output :

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

解决方案

You copy "RRRRRRRRRRRRRRRRRRRRR" into tmp_data, then exit the function, discarding tmp_data altogether (btw without freeing it, so you have a memory leak there). The next call to fun_call will create a new tmp_data local variable, whose value has no relation to what you set it before to. However, name_data_map is declared static, so it is allocated only once (on the first call to fun_call), and reused afterwards, keeping the value you put into it in the previous call (and that value is in fact a different memory block from the one you copy the R's into later).

Update - a more detailed explanation

Here

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

you allocate a memory block, copy "Ravindra Kumar" into it and store a pointer to it in the map. At this point, name_data_map[name] and tmp_data point to the same memory block. Graphically it might roughly look something like this (assuming, for the sake of simplicity, that the two text literals are stored in memory consecutively, which may or may not be the case in real life):

name_data_map[name] ----
                        ˇ
tmp_data ---------------
                        ˇ
raw memory    ..........Ravindra Kumar\0RRRRRRRRRRRRRRRRRRRRR\0............

If you modified the contents of that memory block (by e.g. copying a different text into tmp_data) the change would be visible through name_data_map[name] too, since both of these point to the same memory location.

However, this would not work vice versa: after changing the map value, e.g.

    name_data_map[name]=str1;

the program state would look like this:

name_data_map[name] --------------------
                                        ˇ
tmp_data ---------------
                        ˇ
raw memory    ..........Ravindra Kumar\0RRRRRRRRRRRRRRRRRRRRR\0............

making the two pointers point to different locations, thus a change in one would not affect the other. So note that there is a fundamental difference between changing the value of a pointer, vs changing the value of the memory it points to.

You do exactly the former a few lines later, just with tmp_data:

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

The first line changes the value of tmp_data, so now it no more points to the same place as name_data_map[name]! After that, whatever you do with the newly allocated memory block, it won't affect name_data_map[name] anymore. This is why you failed to change it.

If we declare the map as non static, than we can change it right ?

Wrong. Declaring your map static has no effect on this - it only affects the scope of your map. A nonstatic map would cease to exist when you exit from fun_call, losing all the values stored in it. While it is alive, you can change its values, regardless of it being static or not. You just need to use the right pointer for it.

If your aim was to change the value stored in the map via tmp_data, just drop the second malloc and modify the first one to allocate a longer block (as str1 is longer than str, so trying to copy str1 into a buffer having the length of str results in buffer overrun, i.e. undefined behaviour). After that, you should have a working - although nasty - code, as it is generally not a good idea to try and modify values in a map "behind its back". Moreover, mixing C constructs (malloc and raw pointers, especially void*) in C++ code is a Bad Idea. If you are only experimenting, it is acceptable - bot please don't ever do this in production code. And your intention was something different, please clarify.

这篇关于C ++程序与地图 - 解释下面的程序如何工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆