たとえば、私はいくつかのクラスを持っていDataPacket
ます。違いは何ですか:
auto packet = DataPacket();
と
DataPacket packet;
?
最初の質問に答えるためauto
に、生成されたコードに違いはありません:
auto packet = DataPacket();
と
DataPacket packet = DataPacket();
しかし、それはあなたが書いたものではありません。
元の質問では、最初のものは値で初期化された一時を作成し、それからコピーで初期化packet
します。これには、アクセス可能な非明示的なコピーまたは移動コンストラクターが必要であり、型をデフォルトで構築できる必要があり、確実にpacket
初期化されます(コピー/移動コンストラクターにバグがないと仮定します)。packet
type はデフォルトで構築できますが、オブジェクトに単純なデフォルト コンストラクターがある場合は、オブジェクトを初期化しないままにします。次に例を示します。
struct DataPacket { int i; };
{
DataPacket packet = DataPacket();
++packet.i; // OK
}
{
DataPacket packet;
++packet.i; // undefined behaviour
}
以下のコメントで Xeo が指摘しているように、これらの違いはそれほど大きくありません。
auto packet = DataPacket();
DataPacket packet{};
それらの2番目も値の初期化を保証するため、その場合の違いは、前者がアクセス可能な非明示的なコピーまたは移動コンストラクターを必要とすることです。
アクセス可能なコピー/移動コンストラクターが必要なすべてのケースで、コピー (または移動) が省略されていない場合、生成されるコードはコピー/移動のために異なります。しかし実際には、最新のすべてのコンパイラで省略されるため、生成されるコードは同一になります。
1 つ目はコピー初期化で、コピーまたは移動コンストラクターにアクセスできない場合は失敗します。
コンパイラの観点からは、変数を明示的に宣言すると、変数の親の型を指定できること以外に違いはありません。文体的には読みやすさに影響します (ただし、それがプラスの効果かマイナスの効果かは人によって異なります)。
編集:指摘されたように、最初のものはコピー構築を行い、2番目のものはデフォルトのコンストラクタを使用します。ここで見つかった違いのペダントな説明。
auto キーワードは、式の型がわからない場合に役立ちます。基本的に、コンパイル時に変数の型を決定するようにコンパイラに要求しています。コンパイラに関する限り、auto キーワードを使用することと型を明示的に使用することの間にまったく違いはありません。
auto キーワードを使用して、関数の戻り値の型を決定することもできます。その戻り値の型は、コンパイル時までわかりません (一部のテンプレート化された関数で発生します)。このウィキペディアの記事を参照してください:代替関数の構文。
auto キーワードは RTTI を提供しないことに注意してください。auto-type は、コンパイル時に静的に決定されます。
古い C 時代に戻ると、 auto キーワードは、変数が静的データ領域に格納されるのではなく、スタックに「自動」ストレージを持つことを宣言していました。
この場合、2 番目の構文 (「auto」キーワードなし) を使用することをお勧めします。
これは auto が意味を持つ一例です:
map<int, pair<string, double>> M;
.... // Fill up M
// Without "auto":
map<int, pair<string, double> >::iterator it = M.find(5);
// With "auto":
auto autoit = M.find(5);
// Yet another example:
// Without auto:
for (pair<const int, pair<string, double>>& x: M) {
// Do stuff
}
// With auto:
for (auto& x : M) {
// Do stuff
}