サーチ…


備考

キーワードautoは、自動的に推論された型を表す型名です。

これはCから継承されたC ++ 98の予約済みキーワードです。古いバージョンのC ++では、変数に自動保存期間があることを明示的に示すために使用できます。

int main()
{
  auto int i = 5; // removing auto has no effect
}

その古い意味が削除されました。

基本的な自動サンプル

キーワードautoは、変数の型の自動減算を提供します。

ロングタイプの名前を扱うときに特に便利です:

std::map< std::string, std::shared_ptr< Widget > > table;
// C++98
std::map< std::string, std::shared_ptr< Widget > >::iterator i = table.find( "42" );
// C++11/14/17
auto j = table.find( "42" );

範囲ベースのforループで

vector<int> v = {0, 1, 2, 3, 4, 5};
for(auto n: v)
    std::cout << n << ' ';

ラムダと

auto f = [](){ std::cout << "lambda\n"; };
f();        

タイプの繰り返しを避けるために:

auto w = std::make_shared< Widget >();

意外で不必要なコピーを避けるために:

auto myMap = std::map<int,float>();
myMap.emplace(1,3.14);

std::pair<int,float> const& firstPair2 = *myMap.begin();  // copy!
auto const& firstPair = *myMap.begin();  // no copy!

コピーの理由は、返される型が実際にはstd::pair<const int,float>です。

自動および式テンプレート

autoは、式テンプレートの再生に問題が生じることもあります。

auto mult(int c) {
    return c * std::valarray<int>{1};
}

auto v = mult(3);
std::cout << v[0]; // some value that could be, but almost certainly is not, 3.

その理由は、あるoperator*valarrayあなたを参照するプロキシオブジェクト与えvalarray遅延評価の手段としては。 autoを使うと、ぶら下がっている参照が作成されます。 mult代わりにstd::valarray<int>が返された場合、コードは確実に3を出力します。

自動、定数、および参照

autoキーワード自体は、 intchar似た値型を表します。これはconstキーワードと&記号を使用してそれぞれconst型または参照型を表すように変更できます。これらの修飾子は組み合わせることができます。

この例では、 sは値型(その型はstd::stringと推定される)なので、 forループfor繰り返すたびにベクトルからs文字列がコピーされます。

std::vector<std::string> strings = { "stuff", "things", "misc" };
for(auto s : strings) {
    std::cout << s << std::endl;
}

ループの本体が( s.append(" and stuff")呼び出すなどして) s変更するs.append(" and stuff") 、元のstringsメンバーではなく、このコピーのみが変更されstrings

一方、 sauto&で宣言されている場合、それは参照型( std::string&と推論される)なので、ループの各反復でベクトルの文字列への参照が割り当てられます。

for(auto& s : strings) {
    std::cout << s << std::endl;
}

このループの本体では、 sを変更すると、参照するstringsの要素に直接影響します。

最後に、 sconst auto&と宣言されている場合は、const参照型になります。つまり、ループの各繰り返しでベクトルの文字列へのconst参照が割り当てられます。

for(const auto& s : strings) {
    std::cout << s << std::endl;
}

このループの本体内では、 sは変更できません(つまり、非constメソッドは呼び出すことができません)。

使用する場合autoレンジベースとのforループを、使用することが一般的に良い方法であるconst auto&これは、不要なコピーを回避するので、ループ本体は、上にループされる構造を変更しない場合。

末尾の戻り値の型

末尾の戻り値の型の構文ではautoが使用されます。

auto main() -> int {}

これは

int main() {}

主にstd::declval<T>代わりにパラメータを使用するdecltypeと組み合わせると便利です:

template <typename T1, typename T2>
auto Add(const T1& lhs, const T2& rhs) -> decltype(lhs + rhs) { return lhs + rhs; }

汎用ラムダ(C ++ 14)

C ++ 14

C ++ 14では、lambda引数にautoを使用できます。

auto print = [](const auto& arg) { std::cout << arg << std::endl; };

print(42);
print("hello world");

そのラムダは、

struct lambda {
    template <typename T>
    auto operator ()(const T& arg) const {
        std::cout << arg << std::endl;
    }
};

その後

lambda print;

print(42);
print("hello world");

自動およびプロキシオブジェクト

場合によっては、 autoはプログラマーが期待したとおりに動作しないことがあります。タイプの控除が適切でない場合でも、タイプはその式を推論します。

たとえば、プロキシオブジェクトがコード内で使用される場合、次のようになります。

std::vector<bool> flags{true, true, false};
auto flag = flags[0];
flags.push_back(true);

ここでflagboolではなく、 std::vector<bool>::referenceです。テンプレートvector bool特殊化の場合、 operator []は変換演算子operator bool定義されたプロキシオブジェクトを返します。

flags.push_back(true)がコンテナを変更すると、この擬似参照はもはや存在しなくなった要素を参照してダングリングする可能性があります。

また、次の状況を可能にします。

void foo(bool b);

std::vector<bool> getFlags();

auto flag = getFlags()[5];
foo(flag);

vectorは直ちに破棄されるため、 flagは破棄された要素への擬似参照となります。 foo呼び出すと、未定義のビヘイビアが呼び出されます。

このような場合、 autoで変数を宣言し、推論したい型にキャストして初期化することができます:

auto flag = static_cast<bool>(getFlags()[5]);

その時点で、単にautobool置き換えるのが理にかなっています。

プロキシオブジェクトが問題を引き起こす別のケースは、 式テンプレートです。その場合、テンプレートは効率のために現在の完全式を超えて最後には設計されていない場合があり、次のプロキシオブジェクトを使用すると未定義の動作が発生します。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow