244

私はauto、複雑なテンプレート化された型に対して C++11 標準で利用可能な new キーワードを使用してきました。しかし、私は次のようなことにも使用しています:

auto foo = std::make_shared<Foo>();

そして、より懐疑的に:

auto foo = bla(); // where bla() return a shared_ptr<Foo>

このトピックに関する議論はあまり見たことがありません。auto型は多くの場合、ドキュメンテーションおよびサニティ チェックの形式であるため、過剰に使用される可能性があるようです。この新機能を使用する際にどこに線を引きautoますか?また、この新機能の推奨される使用例は何ですか?

明確にするために:私は哲学的な意見を求めているわけではありません。標準委員会によるこのキーワードの意図された使用を求めています。おそらく、その意図された使用が実際にどのように実現されているかについてコメントしてください。

4

15 に答える 15

148

auto型の書き方が一目でわかりにくいが、式の右辺の型が一目瞭然な場合はキーワードを使うべきだと思います。たとえば、次を使用します。

my_multi_type::nth_index<2>::type::key_type::composite_key_type::
    key_extractor_tuple::tail_type::head_type::result_type

boost::multi_indexであることはわかっていても、 で複合キー タイプを取得しますintint将来変更される可能性があるため、ただ書くことはできません。autoこの場合は書きます。

したがってauto、特定のケースでキーワードが読みやすさを改善する場合は、それを使用してください。タイプが何を表しautoているかが読者に明らかな場合は、書くことができます。auto

ここではいくつかの例を示します。

auto foo = std::make_shared<Foo>();   // obvious
auto foo = bla();                     // unclear. don't know which type `foo` has

const size_t max_size = 100;
for ( auto x = max_size; x > 0; --x ) // unclear. could lead to the errors
                                      // since max_size is unsigned

std::vector<some_class> v;
for ( auto it = v.begin(); it != v.end(); ++it )
                                      // ok, since I know that `it` has an iterator type
                                      // (don't really care which one in this context)
于 2011-06-22T04:51:39.257 に答える
64

特に副作用が心配されないように、autoできる限りどこでも使用してください。const auto明らかな場合を除いて型について心配する必要はありませんが、型は静的に検証されるため、繰り返しを避けることができます。auto実行できない場合は、式に基づいて型をコントラクトdecltypeとして意味的に表現するために使用できます。コードは異なって見えますが、ポジティブな変化になります。

于 2011-06-22T05:41:47.980 に答える
56

簡単。タイプが何であるかを気にしない場合に使用します。例えば

for (const auto & i : some_container) {
   ...

ここで気にするiのは、コンテナに入っているものだけです。

typedef に少し似ています。

typedef float Height;
typedef double Weight;
//....
Height h;
Weight w;

hここでは、 andwが float であるか double であるかは気にしません。ただ、 height と weight を表現するのに適した型であることに注意してください。

または検討する

for (auto i = some_container .begin (); ...

ここで私が気にかけているのは、それが適切なイテレータであり、 をサポートしoperator++()ていることだけです。この点では、ダック タイピングのようなものです。

また、ラムダの型は綴ることができないので、auto f = []...良いスタイルです。代替手段はにキャストすることstd::functionですが、それにはオーバーヘッドが伴います。

の「悪用」としか思えませんauto。私が想像できる最も近いのは、重要な型への明示的な変換を自分自身から奪うことです-しかし、あなたはそれを使用せずauto、目的の型のオブジェクトを構築します。

副作用を発生させずにコードの冗長性をいくらか取り除くことできれば、そうするの良いことです。

反例(他の人の回答から借用):

auto i = SomeClass();
for (auto x = make_unsigned (y); ...)

ここでは、型が何であるかを気にするので、次のように書く必要がSomeclass i;ありますfor(unsigned x = y;...

于 2011-09-19T14:31:36.573 に答える
46

頑張れ。autoコードの記述が容易になる場所ならどこでも使用できます。

どの言語のすべての新機能も、少なくとも一部のタイプのプログラマーによって乱用されます。残りの経験豊富なプログラマーが適切な使用の境界を学ぶのは、一部の経験豊富なプログラマー (初心者ではない) による適度な乱用によってのみです。通常、極端な使いすぎは良くありませんが、使いすぎは機能の改善やそれに代わる優れた機能につながる可能性があるため、良いこともあります。

しかし、次のような数行以上のコードで作業していた場合

auto foo = bla();

タイプがゼロ回示されている場合、それらの行を変更してタイプを含めることができます。最初の例は、型が 1 回記述autoされているため、テンプレート化された面倒な型を 2​​ 回記述する必要がなくなるため、優れています。C++++ 万歳。しかし、近くの行で簡単に見えない場合、型をゼロ回明示的に表示すると、少なくとも C++ とその直後の後継者では緊張します。より高い抽象化、ポリモーフィズム、および汎用性を備えた、より高いレベルで動作するように設計された他の言語の場合は、問題ありません。

于 2011-06-22T04:54:13.727 に答える
43

C++ and Beyond 2012の「Ask Us Anything」パネルでは、Andrei Alexandrescu、Scott Meyers、Herb Sutter の間で を使用する場合と使用しない場合について素晴らしい意見交換autoがありました。25:03 の 4 分間のディスカッションにスキップしてください。3 つのスピーカーはすべて、使用しない場合に留意すべき優れた点を示していますauto

私は人々が自分の結論に達することを強くお勧めしますが、私の結論は、次の場合を除いてどこでも使用するautoことでした:

  1. 可読性を損なう
  2. 自動型変換に関する懸念があります (たとえば、コンストラクター、代入、テンプレートの中間型、整数幅間の暗黙的な変換から)。

を自由に使用するとexplicit、後者の懸念が軽減され、前者が問題になる時間を最小限に抑えることができます。

Herb の言葉を言い換えると、「X、Y、Z を行っていない場合は、 を使用してautoください。X、Y、Z が何であるかを学び、auto他のあらゆる場所で使用してください。」

于 2013-03-31T04:59:31.037 に答える
39

はい、使いすぎて読みやすさが損なわれる可能性があります。正確な型が長い、または発話できない、または読みやすさにとって重要ではなく、変数が短命であるコンテキストで使用することをお勧めします。たとえば、反復子の型は通常長くて重要ではないため、次のようautoに機能します。

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

autoここで読みやすさを損なうことはありません。

もう 1 つの例は、長くて複雑なパーサー ルール タイプです。比較:

   auto spaces = space & space & space;

r_and_t<r_and_t<r_char_t<char>&, r_char_t<char>&>, r_char_t<char>&> spaces = 
   space & space & space;

一方、タイプが既知で単純な場合は、明示的に述べた方がはるかに優れています。

int i = foo();

それよりも

auto i = foo();
于 2011-06-22T04:56:36.787 に答える
23

autoEigen や OpenCV などの線形代数ライブラリでよく使用される式テンプレートと組み合わせると、非常に危険な場合があります。

auto A = Matrix(...);
auto B = Matrix(...);
auto C = A * B; // C is not a matrix. It is a matrix EXPRESSION.
cout << C; // The expression is evaluated and gives the expected result.
... // <code modifying A or B>
cout << C; // The expression is evaluated AGAIN and gives a DIFFERENT result.

この種の間違いによって引き起こされるバグは、デバッグするのに大きな苦痛を伴います。左から右への宣言スタイルに auto を使用することに必死になっている場合、考えられる解決策の 1 つは、結果を期待される型に明示的にキャストすることです。

auto C = Matrix(A * B); // The expression is now evaluated immediately.
于 2015-02-20T20:50:58.280 に答える
9

私はauto制限なしで使用していますが、問題はありませんでした。のような単純な型に使用することもありintます。これにより、C++ は私にとって高水準の言語になり、Python のように C++ で変数を宣言できるようになります。Pythonコードを書いた後、私は時々書くことさえあります。

auto i = MyClass();

それ以外の

MyClass i;

autoこれは、キーワードの乱用であると言えます。

多くの場合、私はオブジェクトの正確なタイプが何であるかを気にしません。私はその機能性にもっと興味があります。関数名は通常、それらが返すオブジェクトについて何かを言うので、auto害はありません:例えばauto s = mycollection.size()、私はそれsがある種の整数であり、正確な型が気になるまれなケースでは、関数のプロトタイプをチェックしてみましょう (つまり、コードが書かれたときにアプリオリにではなく、情報が必要なときにチェックする必要があることを好みます。のように、いつか役に立つ場合に備えてint_type s = mycollection.size())。

受け入れられた回答からのこの例に関して:

for ( auto x = max_size; x > 0; --x )

私のコードではauto、この場合でも使用しxています。無署名にしたい場合は、 say という名前のユーティリティ関数を使用しますmake_unsigned。これは、私の懸念を明確に表しています。

for ( auto x = make_unsigned(max_size); x > 0; --x )

免責事項:私は自分の使い方を説明しているだけで、アドバイスをする資格はありません!

于 2011-06-22T15:09:26.777 に答える
2

C++ プログラムの主な問題の 1 つは、初期化されていない変数を使用できることです。これにより、厄介な非決定論的なプログラムの動作が発生します。最新のコンパイラは、プログラムが使用に疲れた場合、適切なメッセージ警告メッセージをスローするようになったことに注意してください。

これを説明するために、以下の C++ プログラムを検討してください。

int main() {
    int x;
    int y = 0;
    y += x;
}

このプログラムを最新のコンパイラ (GCC) を使用してコンパイルすると、警告が表示されます。実際の複雑な製品コードで作業している場合、このような警告はあまり明白ではないかもしれません。

main.cpp: 関数 'int main()' 内:

main.cpp:4:8:警告: 'x' は、この関数で初期化されていない状態で使用されています [-Wuninitialized]

y += x;

    ^

================================================== ============================== autoを使用するプログラムを変更してコンパイルすると、次のようになります。

int main() {
    auto x;
    auto y = 0;
    y += x;
}

main.cpp: 関数 'int main()' 内:

main.cpp:2:10:エラー: 'auto x' の宣言に初期化子がありません

 auto x;

      ^

auto では、初期化されていない変数を使用することはできません。これは、 autoを使い始めると (無料で) 得られる大きな利点です。

この概念とその他の優れた最新の C++ 概念については、C++ の専門家であるHerb ShutterCppCon14の講演で説明しています。

基本に立ち返って!最新の C++ スタイルの要点

于 2014-10-02T21:39:16.597 に答える
1

auto型を推論することが理にかなっている場合に使用します。整数であることがわかっている場合、または文字列であることがわかっている場合は、 int / std::string などを使用してください。ばかげた点に達しない限り、言語機能を「使いすぎる」ことについて心配する必要はありません。またはコードを難読化します。

とにかくそれが私の意見です。

于 2011-06-22T04:52:36.103 に答える
1

TL;DR: 下部の経験則を参照してください。

受け入れられた答えは、次の経験則を示唆しています。

auto型の書き方が一目でわかりにくいが、式の右辺の型が明らかな場合に使用します。

しかし、それはあまりにも限定的すぎると思います。タイプを理解するのに時間をかけなくても、ステートメントは十分に有益であるため、タイプを気にしない場合があります。それはどういう意味ですか?いくつかの回答でポップアップした例を考えてみましょう:

auto x = f();

これが の誤用の例となるのはautoなぜですか? f()の戻り値の型を知らないのですか?まあ、それを知っていれば確かに役立つかもしれませんが、それは私の主な関心事ではありません。さらに問題なのは、xf()がかなり無意味なことです。もし私たちが持っていたら:

auto nugget = mine_gold();

代わりに、通常、関数の戻り値の型が明らかかどうかは気にしません。ステートメントを読んで、私は自分が何をしているのかを知っており、戻り値のセマンティクスについて十分に知っているので、その型も知る必要はないと感じています。

したがって、私の答えは次のとおりです。autoコンパイラが許可するときはいつでも使用してください。

  • 変数名と初期化/代入式では、ステートメントが何をしているかについて十分な情報が得られないと感じています。
  • 変数名と初期化/割り当て式が一緒になって、型がどうあるべきかについて「誤解を招く」情報を提供していると感じます-つまり、 auto の代わりに何が来るかを推測しなければならない場合、推測を行うことができます-そしてそれはこの誤った仮定は、コードの後半で影響を及ぼします。
  • 別の型 (参照など) を強制したい。

また:

  • auto具体的な型に置き換える前に、意味のある名前 (もちろん型名は含まれません) を付けることをお勧めします。
于 2017-03-27T20:41:02.647 に答える
0

autoキーワードはローカル変数にのみ使用でき、引数またはクラス/構造体メンバーには使用できません。そのため、好きな場所で安全に使用できます。私はそれらをたくさん使います。タイプはコンパイル時に推定され、デバッガーはデバッグ中にタイプを表示し、sizeofそれを正しく報告し、decltype正しいタイプを提供します-害はありません。私は使い過ぎとは見なされませんauto

于 2011-06-22T16:12:38.143 に答える
-6

私の苦い経験の 1 つは、ラムダ式で使用することautoです。

auto i = []() { return 0; };
cout<<"i = "<<i<<endl; // output: 1 !!!

実際、ここiは の関数ポインタに解決されますint(*)()。これは単純couttemplate.

このような式は避け autoて、適切なreturn型 (または制御されたdecltype())を配置する必要があります。

上記の例の正しい使い方は、

auto i = []() { return 0; }(); // and now i contains the result of calling the lambda  
于 2011-06-22T04:57:13.227 に答える