サーチ…
備考
キーワード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" );
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
キーワード自体は、 int
やchar
似た値型を表します。これは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
。
一方、 s
がauto&
で宣言されている場合、それは参照型( std::string&
と推論される)なので、ループの各反復でベクトルの文字列への参照が割り当てられます。
for(auto& s : strings) {
std::cout << s << std::endl;
}
このループの本体では、 s
を変更すると、参照するstrings
の要素に直接影響します。
最後に、 s
がconst 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では、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);
ここでflag
はbool
ではなく、 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]);
その時点で、単にauto
をbool
置き換えるのが理にかなっています。
プロキシオブジェクトが問題を引き起こす別のケースは、 式テンプレートです。その場合、テンプレートは効率のために現在の完全式を超えて最後には設計されていない場合があり、次のプロキシオブジェクトを使用すると未定義の動作が発生します。