7

C 文字列をマップ キーとして使用することに問題はありますか?

std::map<const char*, int> imap;

マップ内の要素の順序は重要ではないため、 を使用して順序付けされていれば問題ありませんstd::less<const char*>

私は Visual Studio を使用しており、MSDN (Microsoft 固有) によると:

場合によっては、同一の文字列リテラルを「プール」して、実行可能ファイルのスペースを節約できます。文字列リテラル プーリングでは、コンパイラは、各参照が文字列リテラルの個別のインスタンスを指すのではなく、特定の文字列リテラルへのすべての参照がメモリ内の同じ場所を指すようにします。

一部のケースでのみプールされると書かれているため、文字列リテラルを使用してマップ要素にアクセスするのは悪い考えのようです:

//Could these be referring to different map elements?
int i = imap["hello"];
int j = imap["hello"];

マップ要素が等しいかどうかを判断するためにポインター値ではなく実際の C 文字列が使用されるように、operator==オーバーロードすることは可能ですか?const char*

bool operator==(const char* a, const char* b)
{
    return strcmp(a, b) == 0 ? true : false;
}

C文字列をマップキーとして使用することは良い考えですか?

4

3 に答える 3

8

const char* の operator== をオーバーロードして、ポインター値ではなく実際の C 文字列を使用して、マップ要素が等しいかどうかを判断することは可能ですか?

いいえ、そうではありません。はい、質問で指摘された正確な理由から、それは良い考えではありません。必要がないため、代わりにchar*a を使用できます。std::string(カスタム比較関数を提供できます-simoncが指摘したように、私はそれをお勧めしません)

//Could these be referring to different map elements?
int i = imap["hello"];
int j = imap["hello"];

はい、まだ存在しない要素を参照することもできますが、それらはによって作成されoperator[]、値が初期化されます。割り当てにも同じ問題があります。

imap["hello"] = 0;
imap["hello"] = 1;

マップには 1 つまたは 2 つの要素を含めることができます。

于 2012-12-13T11:31:39.273 に答える
7

C 文字列を比較するカスタム コンパレータを使用してマップを提供できます。

std::map<const char*,YourType,CstrCmp>;

bool CstrCmp::operator()(const char* a, const char* b) const
{
    return strcmp(a, b) < 0;
}
于 2012-12-13T11:33:19.380 に答える
1

まず、マップ キーの順序付けを導入するには、「より小さい」比較を定義する必要があります。マップは、どちらも他方より小さくない場合、2 つの要素が「同等」であることを示します。マップの外部のどこかでメモリ管理を行う必要があるため、マップ キーに char* を使用することはお勧めできません。

マップをクエリする最も現実的なシナリオでは、キーはリテラルではありません。

一方、文字列リテラルのプールを自分で管理し、すべてのリテラルに ID を割り当てると、それらの ID をマップ キーに使用できます。

要約すると、「場合によってはリテラルがプールされる可能性がある」というマイクロソフトの発言に依存しません。マップにリテラルを入力し、キーとしてリテラルを使用してマップをクエリする場合は、キーに enum を使用することもできます。

于 2012-12-13T11:34:33.313 に答える