C++プログラムでauto
変数を使用することに興奮しています。 auto
で宣言された変数は、テンプレートルールを使用して変数の型を推測しますが、数値型に対してどのように機能するかについては混乱しています。私が持っていると仮定します:
auto foo = 12;
foo
のタイプは、合理的にint
またはunsigned char
になります。しかし、後のプログラムで数学を実行し、fooに40億の値を割り当てたとします。その時点で、foo
をunsigned int
またはlong
型にしたいでしょう。
コンパイラは、プログラムの後半で割り当てられる値をどのように予測できますか?
コンパイラは、存在する情報が整数リテラル12
である情報を処理します。したがって、foo
はint
型であると推定されます。何も予想していません。適切な 整数リテラル サフィックスを使用できます。
auto foo = 12ul;
foo
をunsigned long
として推定するように強制します。変数をint
型に定義することはできません。その後、以前使用した型に収まらない別の値を割り当てたという理由だけで、コンパイラが何らかの方法で変数を別の型に変更することを期待します。これを行うと、単純に整数オーバーフローが発生し、未定義の動作になります。
"fooの型は合理的にintまたはunsigned charである可能性があります"
いいえ、できません。 C++のすべての式には型があり、言語で明確に定義されています。あなたの場合、式は整数リテラルであるため、型はリテラルに対応します。具体的にどのタイプであるかは、 rules で定義されます:
リテラルのタイプ
整数リテラルのタイプは、使用される数値ベースと整数サフィックスに依存するタイプのリストから、値が収まる最初のタイプです。
接尾辞なし-int、long int、long long int(C++ 11以降)
"コンパイラは、プログラムの後半で割り当てられる値をどのように予測できますか?"
できない。型は変数を宣言するときに決定され、後で変更することはできません。
Fooの型は合理的にintまたはunsigned charです
それはcould be多くのものですが、実際にはis一つだけです。
整数リテラル12
のタイプはint
です。
期間。
しかし、私のプログラムの後半で、いくつかの計算を行い、fooに40億の値を割り当てたとします。その時点で、fooにunsigned int型またはおそらくlong型を持たせたいと思います。コンパイラは、プログラムの後半で割り当てられる値をどのように予測できますか?
彼らはできませんし、しません。 foo
のタイプは変更されません。 foo
にはauto
型がありません(そのようなものはありません)。タイプはint
です。以降のプログラムは、あなたがint foo = 12;
。推論/自動化はそこで終わります。
その時点で、
foo
にunsigned int
またはlong
型を持たせたいと思います。
それは言語の仕組みではありません。実行時に変数の型を変更することはできません。変数をauto foo = 12;
として定義および初期化する場合、将来の割り当てに関係なく、int foo = 12;
のタイプはであるため、exactlyは12
と同じことint
。
コンパイラは、プログラムの後半で割り当てられる値をどのように予測できますか?
彼らはする必要はありません。後で割り当てられる値は、変数の型に変換されます。値がそのタイプの範囲外である場合、正確なルールは処理しているタイプによって異なります。
私のアドバイスは、これはauto
を使用するのに適した場所ではないということです。どの要素が必要なタイプを決定するかを知っており、それらを直接のコンテキストから推定することはできません。 (ただし、変数を単一の静的割り当てとして記述できる場合、それは起こりません。)
変数が少なくとも40億の値を保持できる必要があることがわかっている場合は、unsigned long
またはlong long int
。または、これらのタイプの幅の不幸な選択(レガシーコードをサポートするためにlong
が32ビット幅であるがネイティブのWordサイズが64ビットであるプラットフォームなど)に対して防御的にコーディングしたい場合は、それを宣言しますuint_fast32_t
またはint_fast64_t
。または、最速ではなく最小のものが必要な場合は、uint_least32_t
。 (場合によっては、最速のコードがキャッシュにほとんどの値を保持するものです!)
本当に欲しいのが、40億の値を保持できる最速の署名付きまたは署名なしのタイプである場合、その意味を言ってください!
個人的には、これらの直接定数にはautoを使用しませんが、値は別のメソッド呼び出しから取得されるか、別の変数から割り当てられます。
別の変数の型と一致するように変数を定義する方法が必要な場合、その変数と相互運用できますが、定数値を割り当てたい場合は、decltypeを使用してそのサイズに互換性があることを確認します。
decltype(otherVar) myVar = 1234;
myVar += otherVar; // will work just as well as otherVar += myVar
いずれの場合でも、型はリテラル定数で指定され、装飾されていない12はintを定義します。
ただし、定数をデコレートできますでU、符号なしにするか、Lで長くするか、LLでさらに長くします。残念ながら、それをshortまたはcharに強制することに相当するものはありません!