web-dev-qa-db-ja.com

特にループでは、新しいC ++ 11 'auto'機能を使用する必要がありますか?

特にforループでautoキーワードを使用する利点と欠点は何ですか?

for(std::vector<T>::iterator it = x.begin(); it != x.end(); it++ )
{
   it->something();
}

for(std::map<T>::iterator it = x.begin(); it != x.end(); it++ )
{
   it->second->something();
}

for(auto it = x.begin(); it != x.end(); it++ )
{
   it->??
}

マップまたはベクターのイテレータがあるかどうかわからない場合は、firstまたはsecondを使用するか、オブジェクトのプロパティに直接アクセスするかどうかはわかりません。 ?

これは、キーワードvarを使用するかどうかに関するC#の議論を思い出させます。私がこれまでに得ている印象は、C++の世界では、人々はautoキーワードを採用する準備ができており、C#の世界のvarよりも少ない争いであるということです。私にとって最初の本能は、変数の型を知りたいので、その変数に対して実行できるはずの操作を知ることができます。

20
User

メタプログラミングなどのために、C#型よりも型が非常に複雑で複雑になる可能性があるため、C++での動機はさらに極端です。 autoは、明示的なタイプよりも書き込みと読み取りが高速であり、より柔軟/保守可能です。つまり、入力を開始しますか

boost::multi_map<NodeType, indexed_by<ordered_unique<identity<NodeType>>, hashed_non_unique<identity<NodeType>, custom_hasher>>::iterator_type<0> it

それは完全なタイプでさえありません。いくつかのテンプレート引数を見逃しました。

40
DeadMG

あなたの例では:

for(auto it = x.begin(); it != x.end(); i++)
{
  it->??
}

x visibleの宣言が必要です。したがって、itのタイプは明白です。 xのタイプが明確でない場合、メソッドが長すぎるか、クラスが大きすぎます。

28
kevin cline

異議!読み込まれた質問。

3つ目のコードに??が含まれているのに、1つ目と2つ目のコードには含まれていない理由を教えてください。公平を期すために、コードは次のように読み取る必要があります

for(std::vector<T>::iterator it = x.begin(); it != x.end(); i++)
{
   it->???
}

for(std::map<T>::iterator it = x.begin(); it != x.end(); i++)
{
   it->second->???
}

そこ。 autoを使用していなくても同じ問題。

そして、すべての場合において、答えは同じです:コンテキストが重要です。コードの一部について単独で意味のある話をすることはできません。テンプレートではなく具体的​​な型を使用したとしても、コードの読者は型の宣言について知っておく必要があるため、問題が別の場所に移動しただけです。

これらの状況でautoを使用するとコードが判読不能になる場合は、コード設計に問題があることを警告する記号として扱う必要があります。もちろん、ビット操作やレガシーAPIを扱う場合など、低レベルの詳細が重要な場合もあります。その場合、明示的な型が読みやすくなることがあります。しかし、一般的には-いいえ。

varについては(明示的に言及したため)、C#コミュニティにはvarを使用した vast consensus もありますfor。その使用に反対する議論は一般的に 誤解に基づいて構築された です。

14
Konrad Rudolph

プロ

あなたのコード:

for(std::vector<T>::iterator it = x.begin(); it != x.end(); i++)

テンプレートに依存する名前のため、コンパイルされません。

これは正しい構文です:

for( typename std::vector<T>::iterator it = x.begin(); it != x.end(); i++)

型宣言の長さを見てください。これは、autoキーワードが導入された理由を示しています。この :

for( auto it = x.begin(); it != x.end(); i++)

より簡潔です。だから、これはプロです。


CON

あなたは少し注意する必要があります。キーワードautoを使用すると、宣言した型を取得できます。

例えば ​​:

std::vector< int > v{ 1, 2, 3, 4 };
for ( auto it : v )
{
  ++ it;   // ops modifying copies of vector's elements
}

std::vector< int > v{ 1, 2, 3, 4 };
for ( auto & it : v )   // mind the reference
{
  ++ it;   // ok, vector's elements modified
}

結論として:はい、それをすべきですが、使いすぎないでください。一部の人々はそれを使いすぎて、次の例のようにautoをどこにでも置く傾向があります:

auto i = 0;

int i = 0;
11
BЈовић

はい、そうすべきです! autoはタイプを消去しません。 x.begin()が「わからない」場合でも、タイプを誤って使用しようとすると、コンパイラーはそれを認識し、エラーを報告します。また、mapvector<pair<Key,Value>>でエミュレートすることは珍しいことではないため、autoを使用するコードは両方の辞書表現で機能します。

6
zvrba

はい、デフォルトのルールとしてautoを使用する必要があります。タイプを明示的に指定するよりもメリットがあります。

  • コンパイラがすでに認識しているものを入力することはありません。
  • 変数のタイプを戻り値のタイプの変更に「追随」させます。
  • そうすることで、ローカル変数の初期化で暗黙的な変換とスライスのサイレント導入が防止されます。
  • これにより、テンプレートで明示的な型計算を行う必要がなくなります。
  • これにより、戻り値の型に長い名前を付ける必要がなくなります。 (コンパイラの診断からコピーして貼り付けたもの)

ここで選択できます。選択肢がない場合もあります:

  • ラムダの型のような、発話できない型の変数の宣言を許可します。

autoの機能を正確に理解していれば、欠点はありません。

4