web-dev-qa-db-ja.com

C ++自動キーワード。なぜ魔法なのですか?

私がC++の学習に使用したすべての資料から、autoは常に、目的を果たさない奇妙なストレージ期間指定子でした。しかし、つい最近、私はそれをそれ自体で型名として使用するコードに遭遇しました。好奇心から試してみましたが、たまたま私が割り当てたもののタイプを想定しています!

突然STLイテレーター、そしてテンプレートを使用するものはすべて、10倍簡単に記述できます。 Pythonのような「楽しい」言語を使用しているように感じます。

このキーワードは私の人生のどこにありましたか? Visual Studio専用であるか、ポータブルではないということで、私の夢を実現しますか?

126
Anne Quinn

autoは、C++がCから「継承」するキーワードで、ほぼ永遠に存在していましたが、許可されないか、デフォルトで想定される2つの条件しかなかったため、事実上使用されませんでした。

推定型を意味するautoの使用は、C++ 11で新しくなりました。

同時に、auto x = initializerは、_template_type_deductionが関数テンプレートで機能するのと同じ方法で、xのタイプからinitializerのタイプを推定します。次のような関数テンプレートを検討してください。

template<class T>
int whatever(T t) { 
    // point A
};

ポイントAでは、Tにパラメーターに渡された値に基づいて、whateverに型が割り当てられています。 auto x = initializer;を実行すると、同じ型の推論が使用されて、xの型が初期化に使用されたinitializerの型から決定されます。

これは、コンパイラがautoを実装するために必要な型推論メカニズムのほとんどが既に存在し、C++ 98/03を実装しようとしたコンパイラでもテンプレートに使用されたことを意味します。そのため、autoのサポートを追加することは、本質的にすべてのコンパイラチームにとって明らかに簡単でした。非常に迅速に追加され、それに関連するバグもほとんどなかったようです。

この回答が最初に書かれたとき(2011年、インクがC++ 11標準で乾く前)、autoはすでにかなり移植性がありました。今日では、すべての主流のコンパイラ間で完全に移植可能です。それを避ける唯一の明白な理由は、Cコンパイラと互換性のあるコードを書く必要がある場合、またはそれをサポートしていないことがわかっているニッチコンパイラをターゲットにする特定のニーズがある場合です(たとえば、まだコードを書く人もいます) Borland、Watcomなどのコンパイラを使用するMS-DOSの場合、数十年にわたって大幅なアップグレードは行われていません)。メインストリームコンパイラのいずれかの合理的に最新のバージョンを使用している場合、それを避ける理由はまったくありません。

128
Jerry Coffin

一般的には役に立たないキーワードを使用して、新しいより優れた機能を与えるだけです。 C++ 11の標準であり、C++ 11をサポートしているほとんどのC++コンパイラでもサポートされます。

19
Nicol Bolas

この機能は、あなたの人生全体ではありませんでした。 2010バージョン以降、Visual Studioでサポートされています。これは新しいC++ 11機能であるため、Visual Studio専用ではなく、移植可能です。ほとんどのコンパイラはすでにサポートしています。

11

変数の場合、宣言されている変数の型が初期化子から自動的に推測されることを指定します。関数の場合、戻り値の型が末尾の戻り値の型であるか、戻りステートメントから推定されることを指定します(C++ 14以降)。

構文

auto variable initializer   (1) (since C++11)

auto function -> return type    (2) (since C++11)

auto function   (3) (since C++14)

decltype(auto) variable initializer (4) (since C++14)

decltype(auto) function (5) (since C++14)

auto :: (6) (concepts TS)

cv(optional) auto ref(optional) parameter   (7) (since C++14)

説明

1)ブロックスコープ、名前空間スコープ、forループの初期化ステートメントなどで変数を宣言する場合、キーワードautoを型指定子として使用できます。初期化子の型が決定されると、コンパイラは、関数呼び出しからのテンプレート引数の推論の規則を使用して、キーワードautoを置き換える型を決定します(詳細については、テンプレート引数の推論#その他のコンテキストを参照)。キーワードautoには、constや&などの修飾子が付随している場合があり、これらの修飾子は型の推定に参加します。たとえば、const auto& i = expr;を指定すると、関数呼び出しtemplate<class U> void f(const U& u)がコンパイルされた場合、iの型は架空のテンプレートf(expr)の引数uの型とまったく同じです。したがって、auto &&は、初期化子に従って左辺値参照または右辺値参照のいずれかとして推測され、範囲ベースのforループで使用されます。 autoを使用して複数の変数を宣言する場合、推定される型は一致する必要があります。たとえば、宣言auto i = 0, d = 0.0;の形式は正しくありませんが、宣言auto i = 0, *p = &i;の形式は正しく、autoはintとして推測されます。

2)末尾の戻り型構文を使用する関数宣言では、キーワードautoは自動型検出を実行しません。構文の一部としてのみ機能します。

3)末尾の戻り型構文を使用しない関数宣言では、キーワードautoは、テンプレート引数の推論の規則を使用して戻り型がreturnステートメントのオペランドから推定されることを示します。

4)変数の宣言された型がdecltype(auto)である場合、キーワードautoはその初期化子の式(または式リスト)に置き換えられ、実際の型はdecltypeの規則を使用して推定されます。

5)関数の戻り値の型がdecltype(auto)として宣言されている場合、キーワードautoはそのreturnステートメントのオペランドに置き換えられ、実際の戻り値の型はdecltypeの規則を使用して推定されます。

6)auto ::形式のネストされた名前指定子は、制約型プレースホルダーの推論規則に従ってクラスまたは列挙型に置き換えられるプレースホルダーです。

7)ラムダ式のパラメーター宣言。 (C++ 14以降)関数パラメーター宣言。 (TSの概念)

NotesC++ 11まで、autoにはストレージ期間指定子のセマンティクスがありました。 auto f() -> int, i = 0;のように、1つの宣言で自動変数と自動変数を混在させることはできません。

詳細情報: http://en.cppreference.com/w/cpp/language/auto

8

どこにも行きません... C++ 11の実装における新しい標準C++機能です。そうは言っても、オブジェクト宣言を簡素化し、特定の呼び出しパラダイム(つまり、範囲ベースのforループ)の構文をクリーンアップするための素晴らしいツールですが、使いすぎたり乱用したりしないでください:-)

3
Jason