2

私は相対的に C/C++ 初心者ですが、C# や他の多くの言語の経験があり、現在 C++ でゲーム エンジンを構築しています。

入力システム (キー/マウス/ジョイスティック) については、列挙型ではなく、文字列リテラルを使用してゲーム固有の入力イベントの構成を簡素化するというアイデアがありました。しかし、C コンパイラがそれをどのように最適化するかは完全にはわかりません。文字ごとの文字列比較を毎回行うのは非効率的かもしれません。

基本的な考え方は次のとおりです。デバイス イベントから「ゲーム固有のイベント」へのマッピングは、int/enum キーと const char * 値を持つ std::map になります。

Mappings[ KEY_X ] = "Jump";
Mappings[ KEY_Y ] = "Shoot";
Mappings[ MOUSE_1 ] = "Shoot";

これらは、ハードコーディングされたり、構成ファイルからロードされたりする可能性があります (文字列により、解析と保存が簡素化され、新しいイベント タイプが追加されます)。

その後、ゲームでは、ゲーム固有のイベントのみを扱うことができます。

if ( IsDown( "Jump" ) ) {
}
if ( IsSinglePress( "Shoot" ) ) {
}

問題は、すべての文字列リテラルと const char * が魔法のように最適化され、列挙型や整数定数と同じくらい効率的になるでしょうか? 例えば

if ( IsDown( GAMEKEY_SHOOT ) ) {
   // ...
}

それとも、文字列比較などを行うのでしょうか? コンパイラが同じ文字列リテラルのインスタンスを見て、それを一度保存​​し、全体で単一のポインター値を使用することを願っていますが、よくわかりません。

4

4 に答える 4

3

すべての文字列定数が同じファイルにある場合、それらは同じメモリ位置に折りたたまれている可能性があります。それらが別々にコンパイルされる複数のファイルにある場合、またはそれらを動的に読み込む場合、それらはそうではありません。

C(++)を実行しているので、2つの方法で文字列を比較できます(そして、質問ではそれについて何も言っていません):ポインターID(==)または文字ごとの比較(strncmp)。前者を実行している場合、コンパイラの気まぐれに依存するため、非常に信頼性が低くなります(2番目のケースでは必ず失敗します)。後者の場合、文字列の比較が行われることがわかります。

頭痛の種を避け、列挙型または定数という、正しい方法であることがすでにわかっている正しい方法で実行してください。入出力で一度変換すると、内部で数値として処理できるため、高速で安全です。

于 2012-12-10T00:15:30.467 に答える
2

列挙型と文字列の間の変換について数回言及しています。これが私のやり方です。(信用/非難はアイデアのgccに行くと思います。)action.defのようなファイルを作成します

ENUM(Jump)
ENUM(Shoot)

ヘッダーファイルで、次のように列挙型を定義します

#define ENUM(a) a,
Enum Actions {
#include "action.def"
};
#undef ENUM

列挙型メンバーを文字列にマップする必要がある .cpp ファイルで、これを行います

struct EnumMap {
    int value;
    const char * name;
}
#define ENUM(a) { (int) a, #a },
struct EnumMap {
#include "action.def"
} ActionMap[];
#undef ENUM

次に、コードは ActionMap[] を使用して列挙値を文字列に変換し、その逆に変換します。

于 2012-12-10T01:39:39.200 に答える
1

同じ文字列リテラルを複数回書き出すと、とにかくエラーが発生しやすくなります。そのうちの1つを誤って入力した場合はどうなりますか?

グローバルを使用する場合、まったく同じ変数を参照しているため、グローバルが同じアドレスを持つことを確認できます。

char const * const Jump = "Jump";

(またはヘッダーで宣言し、単一の.cppで実際の文字列値を初期化します)

および次のように使用します。

Mappings[ KEY_X ] = Jump;
...
if ( IsDown( Jump ) ) {
    ...

これが素晴らしいスタイルであるとは思いません(そうではありません)。列挙型と文字列表現の間に組み込みのリンクが必要な場合は、それを取得するためのより良い方法があります。

于 2012-12-10T00:19:31.410 に答える
1

標準に関する限り、コンパイラは、同じ文字列リテラルのさまざまなインスタンスがメモリの同じ位置を指すようにする場合とそうでない場合があります。

すべての文字列リテラルが異なる (つまり、重複しないオブジェクトに格納される) かどうかは、実装で定義されます。

(C++11、§2.14.5 ¶12)

また、値が動的に割り当てられる場合、何らかのバッファから取得されます...文字列リテラルとは異なるアドレスを持っていることは確かです。したがって、一方が他方と等しいかどうかを確認する唯一の正しい方法は、文字列のバイトを比較することです (のstrcmpような方法で)。これは明らかにポインタ比較よりも遅くなります。

その上、これらの設定に文字列を使用する意味がわかりません: enums を使用するだけで、少なくとも同じくらい高速に (おそらくより高速に) 実行され、エラーが発生しにくくなります (間違った列挙値を記述すると、コンパイル エラーが発生します) 、文字列定数でタイプミスをすると、黙って受け入れられます)。

于 2012-12-10T00:14:22.863 に答える