次の方法で共有


auto (C++)

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

Note

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

構文

auto declarator initializer ;

[](auto param1 , auto param2 ) {};

解説

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 キーワードは、型のプレースホルダーであり、それ自体が型ではありません。 そのため、auto キーワードは、sizeof と (for C++/CLI) typeid などの演算子やキャストでは使用できません。

実用性

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

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

後続の戻り値の型

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

参照と cv 修飾子

auto を使用すると、参照、const 修飾子、volatile 修飾子がドロップされます。 次の例を確認してください。

// 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 です。そのため、参照修飾子が auto によってドロップされていない場合のように、出力は 11 12 ではなく、11 11 になります。

かっこ付き初期化子を使用した型推論 (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 auto キーワードを他の型指定子と組み合わせることはできません。
C3531 auto キーワードで宣言されたシンボルには初期化子が必要です。
C3532 auto キーワードを不適切に使用して型を宣言しました。 たとえば、メソッドの戻り値の型または配列を宣言しました。
C3533C3539 パラメーターまたはテンプレート引数を auto キーワードで宣言することはできません。
C3535 メソッドまたはテンプレート パラメーターを auto キーワードで宣言することはできません。
C3536 初期化前にシンボルを使用することはできません。 実際には、変数はその変数自体を初期化するために使用できないことを意味します。
C3537 auto キーワードで宣言された型にはキャストできません。
C3538 auto キーワードで宣言されている宣言子リスト内のすべてのシンボルは、同じ型に解決する必要があります。 詳細については、「宣言と定義」を参照してください。
C3540C3541 sizeoftypeid 演算子は 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 (変数の型の推測)
sizeof 演算子
typeid
operator new
宣言と定義
ラムダ式の例
初期化子
decltype