auto (C++)

宣言された変数の型を、その初期化式から推測します。

Note

C++ 標準ではこのキーワードの元の意味と変更後の意味が定義されます。 Visual Studio 2010 より前までは、auto キーワードは自動ストレージ クラスで変数を宣言していました。つまりローカルの有効期間のある変数です。 Visual Studio 2010 以降、auto キーワードは、その宣言の初期化式から変数の型を推測し、変数を宣言します。 /Zc:auto[-] コンパイラ オプションは、auto のキーワードの意味を制御します。

構文

autodeclaratorinitializer;

[](autoparam1, autoparam2) {};

解説

auto キーワードは、宣言された変数の初期化式、またはラムダ式のパラメーターを使用してその型を推測するようにコンパイラに指示します。

次のような利点があるので、実際に変換が必要な場合を除き、ほとんどの状況で auto キーワードを使用することをお勧めします。

  • 堅牢性: 式の型が変更された場合 (関数の戻り値の型が変更されたときを含む)、動作するだけです。

  • パフォーマンス: 変換がないことを保証します。

  • 利便性: 型名のスペルの難しさや入力ミスを気にする必要がありません。

  • 効率性: コーディングをより効率的にすることができます。

auto を使用したくないと思われる変換ケース:

  • 特定の型が必要であり、それ以外は何も行いません。

  • 式テンプレート のヘルパー型 (例: (valarray+valarray).

auto キーワードを使用するには、型の代わりにこのキーワードを使用して変数を宣言し、初期化式を指定します。 さらに、auto キーワードを constvolatile、ポインタ (*)、参照(&)、右辺値参照 (&&) などの指定子や宣言子で修飾することができます。 コンパイラは初期化式を評価し、その情報を使用して変数の型を推測します。

auto 初期化式には、いくつかの形式があります。

  • auto a { 42 }; などの汎用初期化構文。
  • auto b = 0; などの割り当て構文。
  • auto c = { 3.14159 }; などの 2 つの前の形式を組み合わせた汎用割り当て構文。
  • 直接の初期化、または auto d( 1.41421f ); などのコンストラクター形式の構文。

詳細については、「初期化子」と、このドキュメントの後の方のコード例を参照してください。

auto が範囲ベース for のステートメントでループ パラメーターを宣言するために使用されている場合、たとえば、for (auto& i : iterable) do_action(i); などの別の初期化構文を使用します。 詳細については、「範囲ベースの for ステートメント (C++)」を参照してください。

auto キーワード (keyword)は型のプレースホルダーですが、それ自体は型ではありません。 そのため、autoキャストや演算子 (C++/CLI の場合) typeidではsizeof、キーワード (keyword)を使用できません。

実用性

auto キーワードは、複雑な型を持つ変数を宣言する簡単な方法です。 たとえば、auto キーワードを使用して、初期化式にテンプレート、関数へのポインター、またはメンバーへのポインターが含まれる変数を宣言できます。

auto を使用して、ラムダ式の変数を宣言して初期化することもできます。 ラムダ式の型を認識できるのはコンパイラのみであるため、プログラマが変数の型を宣言することはできません。 詳細については、「ラムダ式の例」を参照してください。

後続の戻り値の型

テンプレート ライブラリの記述を支援するには、decltype 型指定子と共に、auto を使用します。 戻り値の型がテンプレート引数の型に依存する関数テンプレートを使用 auto して decltype 宣言します。 または、別の関数の呼び出しをラップしdecltype、その他の関数の戻り値の型を返す関数テンプレートを使用autoして宣言します。 詳細については、decltypeを参照してください。

参照と cv 修飾子

ドロップ参照、修飾子、constおよびvolatile修飾子の使用auto。 次の例を考えてみましょう。

// cl.exe /analyze /EHsc /W4
#include <iostream>

using namespace std;

int main( )
{
    int count = 10;
    int& countRef = count;
    auto myAuto = countRef;

    countRef = 11;
    cout << count << " ";

    myAuto = 12;
    cout << count << endl;
}

前の例では、myAuto はint参照ではなく 、参照であるためint、参照修飾子が11 1111 12削除autoされていない場合と同様に出力されません。

かっこ付き初期化子を使用した型推論 (C++ 14)

次のコード例は、中かっこを使用して auto 変数を初期化する方法を示しています。 B と C の違いと A と E の違いに注意してください。

#include <initializer_list>

int main()
{
    // std::initializer_list<int>
    auto A = { 1, 2 };

    // std::initializer_list<int>
    auto B = { 3 };

    // int
    auto C{ 4 };

    // C3535: cannot deduce type for 'auto' from initializer list'
    auto D = { 5, 6.7 };

    // C3518 in a direct-list-initialization context the type for 'auto'
    // can only be deduced from a single initializer expression
    auto E{ 8, 9 };

    return 0;
}

制限事項とエラー メッセージ

次の表は、auto キーワードの使用に関する制限事項と、それに対応してコンパイラによって生成される診断エラー メッセージの一覧です。

エラー番号 説明
C3530 キーワード (keyword)をauto他の型指定子と組み合わせることはできません。
C3531 auto キーワードで宣言されたシンボルには初期化子が必要です。
C3532 auto キーワードを不適切に使用して型を宣言しました。 たとえば、メソッドの戻り値の型または配列を宣言しました。
C3533C3539 パラメーターまたはテンプレート引数は、キーワード (keyword)でauto宣言できません。
C3535 キーワード (keyword)では、メソッドまたはテンプレート パラメーターをauto宣言できません。
C3536 シンボルを初期化する前に使用することはできません。 実際には、変数を使用して自身を初期化することはできません。
C3537 キーワード (keyword)で宣言されている型にautoキャストすることはできません。
C3538 auto キーワードで宣言されている宣言子リスト内のすべてのシンボルは、同じ型に解決する必要があります。 詳細については、「宣言と定義」を参照してください。
C3540C3541 sizeof 演算子と typeid 演算子は、キーワード (keyword)で宣言されているシンボルにはauto適用できません。

以下のコード片は、auto キーワードを使用するためのいくつかの方法を示しています。

次の宣言は同等です。 最初のステートメントでは、変数 jint 型として宣言されます。 2 番目のステートメントでは、初期化式 (0) が整数であるため、変数 k は型 int であると推測されます。

int j = 0;  // Variable j is explicitly type int.
auto k = 0; // Variable k is implicitly type int because 0 is an integer.

次の宣言は同じ意味を持ちますが、2 番目の宣言の方が最初の宣言より単純です。 auto キーワードを使用する最も説得力のある理由の 1 つは簡潔さです。

map<int,list<string>>::iterator i = m.begin();
auto i = m.begin();

次のコード片は、for と範囲の for ループが開始されるときに、変数 iterelem の型を宣言します。

// cl /EHsc /nologo /W4
#include <deque>
using namespace std;

int main()
{
    deque<double> dqDoubleData(10, 0.1);

    for (auto iter = dqDoubleData.begin(); iter != dqDoubleData.end(); ++iter)
    { /* ... */ }

    // prefer range-for loops with the following information in mind
    // (this applies to any range-for with auto, not just deque)

    for (auto elem : dqDoubleData) // COPIES elements, not much better than the previous examples
    { /* ... */ }

    for (auto& elem : dqDoubleData) // observes and/or modifies elements IN-PLACE
    { /* ... */ }

    for (const auto& elem : dqDoubleData) // observes elements IN-PLACE
    { /* ... */ }
}

次のコード片は、ポインターを宣言するために、new 演算子とポインター宣言を使用します。

double x = 12.34;
auto *y = new auto(x), **z = new auto(&x);

次のコード片は各宣言ステートメントで複数のシンボルを宣言します。 各ステートメントのすべてのシンボルが同じ型に解決されることに注意してください。

auto x = 1, *y = &x, **z = &y; // Resolves to int.
auto a(2.01), *b (&a);         // Resolves to double.
auto c = 'a', *d(&c);          // Resolves to char.
auto m = 1, &n = m;            // Resolves to int.

次のコード片は、値が 200 の整数として変数 ?: を宣言するために、条件演算子 (x) を使用します。

int v1 = 100, v2 = 200;
auto x = v1 > v2 ? v1 : v2;

次のコード フラグメントは、変数 x を型 int に、変数 y を型 const int への参照に、変数 fp を型 int を返す関数へのポインターに初期化します。

int f(int x) { return x; }
int main()
{
    auto x = f(0);
    const auto& y = f(1);
    int (*p)(int x);
    p = f;
    auto fp = p;
    //...
}

関連項目

キーワード
/Zc:auto (変数型の Deduce)
sizeof 演算子
typeid
operator new
宣言と定義
ラムダ式の例
初期化子
decltype