-1

以下のプログラムでは、tmp_data は最初に「Ravindra Kumar」として出力されます。しかし、マップにコピーした後、「RRRRRRRRRRR」に変更されました。次回印刷するときは、まだ「Ravindra Kumar」が印刷されています。RRRRRRRR を出力すると仮定しますよね?

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

2 に答える 2

2

にコピー"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グラフィック的には、大まかに次のようになります (簡単にするために、2 つのテキスト リテラルが連続してメモリに格納されていると仮定します。実際にはそうである場合とそうでない場合があります)。

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

そのメモリ ブロックの内容を変更した場合 (別のテキストを にコピーするなど)、これらの両方が同じメモリ位置を指しているためtmp_data、変更も表示されます。name_data_map[name]

ただし、これは逆には機能しません。たとえば、マップ値を変更した後

    name_data_map[name]=str1;

プログラムの状態は次のようになります。

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

2 つのポインタが異なる場所を指すようにするため、一方を変更しても他方には影響しません。したがって、ポインタの値を変更することと、ポインタが指すメモリの値を変更することには根本的な違いがあることに注意してください。

次のように、数行後に前者を正確に実行します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、2 番目のブロックを削除しmalloc、最初のブロックを変更してより長いブロックを割り当てます (str1は よりも長いため、 の長さのバッファーstrにコピーしようとすると、バッファー オーバーランが発生します。つまり、未定義の動作)。その後、「背後で」マップの値を変更しようとするのは一般的には良い考えではないため、(厄介ではありますが) 機能するコードが必要です。さらに、C++ コードで C コンストラクト (および生のポインター、特に) を混在させることは、悪い考えです。実験のみを行っている場合は、許容されます。ボットは、実稼働コードでこれを行わないでください。そして、あなたの意図は別のものでした。明確にしてください。str1strmallocvoid*

于 2012-04-26T12:40:29.473 に答える
0

次のコードはより単純で、あなたが望むことをしているようです。マップの値として std::string よりも char* を好む理由はありますか?

#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
于 2012-04-26T13:37:54.323 に答える