自動でC ++コードを理解しにくくしますか?


122

私はハーブサッターによるカンファレンスを見て、そこで彼はすべてのC ++プログラマーの使用を奨励していますauto

C#コードvarを広く使用されていたコードを読む必要があり、コードを理解するのは非常に困難varでした。時間の経過ごとに右側の戻り値の型を確認する必要がありました。しばらくして変数の型を忘れてしまったので、時々複数回!

コンパイラーは型を知っているので、型を書く必要はありませんが、コンパイラーではなくプログラマー向けにコードを書くことは広く受け入れられています。

私はそれがより簡単に書くことも知っています:

auto x = GetX();

より:

someWeirdTemplate<someOtherVeryLongNameType, ...>::someOtherLongType x = GetX();

ただし、これは1回しか記述されず、GetX()戻り値の型が何回あるかを理解するために何度もチェックされますx

これは私に不思議に思いましたauto—C ++コードを理解するのを難しくしますか?


29
毎回本当に戻り値の型を確認する必要がありますか?コードから型が明確でないのはなぜですか?auto多くの場合、すでに読みにくいときに物事を読みにくくします。つまり、関数が長すぎる、変数の名前が不適切などです。
R.マルティーニ・フェルナンデス

25
使用する「技術」autoは、いつ使用するかを決定することによく似ていますtypedef。いつそれが妨げられ、いつ役立つかを判断するのはあなた次第です。
アーヘンソン

18
私は同じ問題を抱えていると思っていましたが、タイプを知らなくてもコードを理解できるだけであることに気付きました。例: "auto idx = get_index();" そのため、idxはインデックスを保持するものです。正確なタイプは、ほとんどの場合、まったく無関係です。
PlasmaHH

31
だからauto x = GetX();、書かxないで、その特定のコンテキストで実際に何をするかを実際に伝えるよりも良い名前を選んでください ... それはとにかくそのタイプよりも便利です。
ジョナサンウェイクリー

11
より多くの型推論を使用すると、プログラマーがコードを読みにくくなる場合は、コードまたはプログラマーに深刻な改善が必要です。
CAマッキャン

回答:


100

簡単な答え:より完全に、私の現在の意見でautoは、auto明示的に変換が必要でない限り、デフォルトで使用する必要があるということです。(より正確には、「...明示的に型にコミットしたい場合を除き、ほとんど常に変換が必要なためです。」)

より長い回答と根拠:

autoに明示的にコミットする場合にのみ、(ではなく)明示的な型を記述します。これは、ほとんどの場合、その型への変換を明示的に取得することを意味します。私の頭の上から、私は2つの主なケースを思い出します:

  • (共通)initializer_listauto x = { 1 };推測する驚きinitializer_list。したくない場合initializer_listは、タイプを言います-すなわち、明示的に変換を要求します。
  • (まれ)auto x = matrix1 * matrix 2 + matrix3;プログラマーに表示されることを意図していないヘルパーまたはプロキシタイプをキャプチャする式テンプレートの場合。多くの場合、その型をキャプチャすることは問題ありませんが、場合によっては、それを実際に折りたたんで計算を実行したい場合は、型を言います(つまり、明示的に変換を要求します)。

使用autoするautoと落とし穴が回避され、コードがより正確になり、保守性と堅牢性が高まり、効率が向上するため、デフォルトでは通常どおり使用されます。「明快さと正確さを第一に書く」という精神で、おおまかに重要度の低い順に:

  • 正しさ:auto保証を使用すると、正しいタイプが得られます。ことわざにあるように、自分自身を繰り返す場合(タイプを冗長に言う)、あなたは嘘をつくことができ、嘘をつきます(間違えます)。ここではいつもの例を示しますvoid f( const vector<int>& v ) { for( /*…*-この時点で、あなたは明示的にイテレータの型を記述する場合、あなたが書くために覚えておきたいconst_iteratorのに対し、(あなたをした?)autoちょうど右のそれを取得します。
  • 保守性と堅牢性:を使用autoする、式の型が変更さautoれたときに正しい型に解決され続けるため、変更に対してコードがより堅牢になります。代わりに明示的な型にコミットする場合、式の型を変更すると、新しい型が古い型に変換されるときにサイレント変換が挿入されるか、新しい型が古い型のように機能するが古い型に変換されないときに不要なビルドが中断しますタイプは、(たとえば、あなたが変更するときmapunordered_map使用して、順番に頼っていない場合は、常に細かいである、autoあなたのイテレータのためにあなたがシームレスに切り替えるだろうmap<>::iteratorunordered_map<>::iterator、しかし、使用してmap<>::iterator どこでも、インターンが歩いていて、退屈な作業をやり遂げることができない限り、機械的なコード修正リップルに貴重な時間を浪費することを明示的に意味します)。
  • パフォーマンス:のでauto保証は暗黙の変換は起こりません、それはデフォルトでは、より良い性能を保証します。代わりにタイプを言うと、それが変換を必要とする場合、期待しているかどうかにかかわらず、多くの場合静かに変換を取得します。
  • 使いやすさ:auto繰り返しdecltype式やのような非効率的な間接参照に頼るのではなく、ラムダやテンプレートヘルパーなど、綴りが難しく発言できないタイプの場合、使用するのが唯一の良いオプションですstd::function
  • 利便性:そして、はい、autoタイピングが少ないです。完全を期すために最後に言及しますが、それはそれを好む一般的な理由ですが、それを使用する最大の理由ではありません。

したがって:autoデフォルトで言うことを好む。それは非常にシンプルでパフォーマンスと明快さの良さを提供するので、そうしなければ自分(そしてコードの将来のメンテナー)を傷つけるだけです。明示的な型にコミットするのは、実際にそれを意味する場合のみです。これは、ほとんどの場合、明示的な変換が必要であることを意味します。

はい、これについて(今)GotWがあります。


14
変換が必要な場合でも、autoは便利です。これにより、タイプを繰り返さずに明示的に変換を要求できますauto x = static_cast<X>(y)。これstatic_castにより、変換が意図的に行われていることが明確になり、変換に関するコンパイラの警告が回避されます。通常、コンパイラの警告を回避することはあまりよくありませんが、を書いstatic_castたときに慎重に検討した変換に関する警告が表示されなくてもかまいません。警告が現在ない場合はこれを行いませんが、将来、タイプが潜在的に危険な方法で変更された場合は警告を取得したいと思います。
Bjarke Hammersholt Roune

6
私が見つけたことの1つautoは、特定の実装ではなく、インターフェイス(OOPの意味ではない)に対してプログラミングするよう努力する必要があるということです。本当にテンプレートでも同じです。Tどこでも使用されているテンプレートタイプのパラメーターがあるため、「コードを読みにくい」と苦情を言いますか?いいえ、そうは思いません。テンプレートでも、インターフェイスに対してコーディングします。コンパイル時のダックタイピングは、多くの人がそれを呼ぶものです。
Xeo

6
「自動保証を使用すると、正しいタイプを取得できます。」まったく真実ではありません。コードの他の部分で規定されている型を取得することのみを保証します。それが正しいかどうかは、背後に隠すと完全に不明確になりますauto
軌道上の明るさのレース

誰もIDEを気にしないことに本当に驚いています...現代のIDEでさえ、auto変数の場合のクラス/構造体定義へのジャンプを正しくサポートしていませんが、ほとんどすべてが明示的な型指定で正しくジャンプします。誰もIDEを使用していませんか?誰もがint / float / bool変数のみを使用していますか?誰もが自己文書化されたヘッダーではなく、ライブラリの外部文書を好むのですか?
-avtomaton

そのGotW:herbsutter.com/2013/08/12/…その「initializer_listサプライズ」がサプライズであることがわかりません。=RHSを囲む中括弧は、他の解釈では意味がありません(中括弧で囲まれたinit-listですが、何を初期化しているのかを知る必要がありますauto。1 である驚くべきはされてauto i{1}も、推論initializer_listではない暗示にもかかわらず、 これはINIT-リストを引き締め取るのではなく、この表現を取り、その型を使用 ...しかし、我々が得るinitializer_listもそこ。ありがたいことに、C ++ 17はこれらすべてを上手く修正しています。
underscore_d

112

それはケースバイケースの状況です。

コードを理解するのが難しくなる場合がありますが、そうでない場合もあります。例えば:

void foo(const std::map<int, std::string>& x)
{
   for ( auto it = x.begin() ; it != x.end() ; it++ )
   { 
       //....
   }
}

実際のイテレータ宣言よりも間違いなく理解やすく間違いなく簡単に記述できます。

私は今、しばらくの間、C ++を使用してきたが、私は忘れると思いますので、私はこれで私の最初のショットでコンパイルエラーを取得したいことを保証することができますconst_iteratorし、最初のために行くだろうiterator... :)

私はこのような場合に使用しますが、実際にタイプを難読化する場所ではありません(あなたの状況など)が、これは純粋に主観的なものです。


45
まさに。一体誰がタイプを気にしますか。イテレータです。型については気にしません。知る必要があるのは、この型を使用して反復できることだけです。
R.マルティーニ・フェルナンデス

5
+1。型に名前を付けたstd::map<int, std::string>::const_iteratorとしても、という名前を付けますので、とにかく名前が型について多くを語っているようではありません。
スティーブジェソップ

4
@SteveJessop:少なくとも2つのことを教えてくれintますstd::string。キーは、値はです。:)
ナワズ

16
@Nawaz:そしてit->second、それはconstイテレータなので割り当てられない。これらの情報はすべて、前の行の内容の繰り返しですconst std::map<int, std::string>& x。物事を複数回言うことは時々より良い情報を提供しますが、決して一般的なルールではありません:
スティーブジェソップ

11
TBH for (anX : x)繰り返しを行っているだけであるので、もっとはっきりさせたいと思いますx。あなたはイテレータを必要とする通常のケースでは、コンテナを変更しているときですが、xあるconst&
MSalters

94

別の方法で見てください。書きますか:

std::cout << (foo() + bar()) << "\n";

または:

// it is important to know the types of these values
int f = foo();
size_t b = bar();
size_t total = f + b;

std::cout << total << "\n";

明示的にタイプを綴ることが役に立たない場合があります。

型に言及する必要があるかどうかの決定は、中間変数を定義して複数のステートメントにコードを分割するかどうかの決定と同じではありません。C ++ 03では、この2つはリンクさautoれていたため、それらを分離する方法と考えることができます。

型を明示的にすることが役立つ場合があります。

// seems legit    
if (foo() < bar()) { ... }

// ah, there's something tricky going on here, a mixed comparison
if ((unsigned int)foo() < bar()) { ... }

変数を宣言する場合、を使用autoすると、多くの式と同じように、型を暗黙的に使用できます。読みやすさを妨げる場合と妨げになる場合は、おそらく自分で決定するようにしてください。

符号付き型と符号なし型を混在させることは、そもそも間違いであると主張できます(実際、符号なし型をまったく使用すべきではないと主張する人もいます)。理由、それは間違いなく間違いだが、それが原因で異なる動作のオペランドの型が極めて重要になるということです。値の型を知る必要があるのが悪いことであれば、おそらくそれらを知る必要がないことも悪いことではないでしょう。他の理由でコードが既に混乱していないという条件で、それで問題ありませんautoか?;-)

特に一般的なコードを書くとき、変数の実際の型が重要ではない場合があります。重要なのは、必要なインターフェースを満たすことです。したがってauto、型を無視する抽象化レベルを提供します(もちろん、コンパイラーはそれを認識しません)。適切な抽象化レベルで作業すると読みやすさが大幅に向上します。「間違った」レベルで作業すると、コードの読み取りが困難になります。


21
+1をauto使用すると、名前のない、または関心のないタイプの名前付き変数を作成できます。意味のある名前が役立つ場合があります。
マンカルス

適切に使用するために符号なしを使用する場合、符号付きと符号なしを組み合わせます:モジュラー演算。正の整数に符号なしを誤用しているのではありません。符号なしを使用するプログラムはほとんどありませんが、コア言語によりsizeof、符号なしとしての無意味な定義が強制されます。
curiousguy

27

IMO、あなたはこれをほとんど逆に見ています。

autoコードが読めなかったり、読めなくなったりすることはありません。戻り値に明示的な型を持つことは、(特定の)特定の関数によってどの型が返されるかが(明らかに)明確でないという事実を補う(ということを望んでいます)。

少なくとも私の意見では、戻り値の型がすぐにはわからない関数がある場合、それはあなたの問題です。関数が行うことはその名前から明らかであり、戻り値の型は関数が行うことから明らかでなければなりません。そうでない場合、それが問題の本当の原因です。

ここに問題がある場合は、ではありませんauto。コードの残りの部分で、明示的な型がコアの問題を見たり修正したりするのを防ぐためのバンドエイドとして十分である可能性はかなり高いです。その実際の問題を修正したら、auto一般的に使用するコードの読みやすさは問題ありません。

私は公平に追加する必要があると思います:そのようなことはあなたが望むほど明白ではなかったいくつかのケースに対処し、問題を修正することもかなり受け入れ難いです。ほんの一例として、私は数年前に以前に別の会社と合併した会社のコンサルティングをしました。彼らは最終的に、実際にマージされるよりも「一緒に押し込まれた」コードベースになりました。構成プログラムは、類似の目的のために異なる(ただし非常に類似した)ライブラリを使用して開始しました。非常に多くの場合、特定の関数によって返される型を推測する唯一の方法は、その関数がどこから発生したかを知ることでした。

そのような場合でも、かなり多くのことを明確にするのに役立ちます。その場合、すべてのコードはグローバル名前空間で始まりました。かなりの量をいくつかのネームスペースに移動するだけで、名前の衝突がなくなり、タイプトラッキングもかなり簡単になりました。


17

一般的な用途で自動が嫌いな理由はいくつかあります。

  1. コードを変更せずにリファクタリングできます。はい、これはautoを使用する利点としてしばしばリストされるものの1つです。関数の戻り値の型を変更するだけで、それを呼び出すコードがすべてautoを使用する場合、追加の作業は必要ありません!あなたはコンパイルをヒットし、ビルドします-0警告、0エラー-そしてあなたは先に進み、機能が使用されている80の場所を調べて潜在的に変更するという混乱に対処することなくコードをチェックインします。

しかし、待って、それは本当に良いアイデアですか?半ダースのユースケースで型が問題になり、そのコードが実際に異なる動作をするようになったらどうなるでしょうか?これは、入力値だけでなく、関数を呼び出す他のクラスのプライベート実装の動作自体を変更することにより、カプセル化を暗黙的に破ることもできます。

1a。私は「自己文書化コード」の概念を信じています。自己文書化コードの背後にある理由は、コメントが古くなる傾向があり、コードが行っていることをもはや反映しなくなるのに対し、コード自体は-明示的な方法で記述されている場合-自明であり、常に最新であるその意図に基づいて、古いコメントと混同することはありません。ただし、コード自体を変更することなくタイプを変更できる場合、コード/変数自体が古くなる可能性があります。例えば:

auto bThreadOK = CheckThreadHealth();

問題を除いて、ある時点でCheckThreadHealth()がリファクタリングされ、boolではなく、エラーステータスを示す列挙値があればそれを返します。しかし、その変更を行った人は、この特定のコード行の検査を見逃し、警告やエラーなしでコンパイルされたため、コンパイラは役に立ちませんでした。

  1. 実際の型が何であるかを決して知ることはできません。これは、多くの場合、自動車の主要な「利点」としてリストされています。「だれが気にしますか?それはコンパイルされます!」と言うことができるとき、なぜ関数があなたに与えているものを学ぶのか。

たぶん作品の一種です。ループの繰り返しごとに500バイトの構造体のコピーを作成しているので、1つの値を検査できますが、コードはまだ完全に機能しているため、一種の動作を言います。そのため、単体テストでも、その単純で無邪気な外観の自動車の背後に不良コードが隠れていることに気付くことはありません。ファイルをスキャンする他のほとんどの人は、一見しただけでは気づかないでしょう。

タイプがわからない場合、これはさらに悪化する可能性がありますが、それが何であるかについて間違った仮定をする変数名を選択すると、実際には1aと同じ結果を達成しますが、最初からではなくリファクタリング後。

  1. 最初にコードを記述するときにコードを入力することは、プログラミングの最も時間のかかる部分ではありません。はい、autoは最初にいくつかのコードの記述を高速化します。免責事項として、私は> 100 WPMと入力するので、他の人ほど気にしないかもしれません。しかし、私がしなければならないのが終日新しいコードを書くことだったら、私は幸せなキャンピングカーになります。プログラミングの最も時間のかかる部分は、コードの再現が難しいエッジケースのバグを診断することです。これは、多くの場合、微妙な非自明な問題に起因します。符号付きと符号なし、フロートと整数、ブールとポインタなど)。

autoは主に、標準ライブラリテンプレートタイプを使用したひどい構文の回避策として導入されたことは明らかです。既に慣れ親しんでいるテンプレート構文を修正しようとするのではなく(既存のすべてのコードが壊れる可能性があるため、ほぼ不可能かもしれません)、基本的に問題を隠すキーワードを追加します。基本的に、「ハック」と呼ばれるものです。

実際、標準ライブラリコンテナでautoを使用することに異論はありません。それは明らかにキーワードが作成されたものであり、標準ライブラリの関数は基本的に目的(またはその種類)で根本的に変更される可能性が低いため、自動で比較的安全に使用できます。しかし、より揮発性が高く、より根本的な変更の対象となる可能性のある独自のコードとインターフェイスで使用することには非常に慎重です。

言語の機能を強化するautoのもう1つの便利なアプリケーションは、型に依存しないマクロでの一時的な作成です。これは以前は本当にできなかったことですが、今はできます。


4
あなたはそれを打ちました。これに+2を与えてほしい。
cmaster

良い「とんでもない」答え。@cmaster:あります。
デデュプリケーター

もう1つの有用なケースを見つけましたauto something = std::make_shared<TypeWithLongName<SomeParam>>(a,b,c);。:-)
Notinlist

14

はい、それを使用しない場合、変数の型を簡単に知ることができますauto。問題は、コードを読み取るために変数の型を知る必要があるかどうかです。時には答えはイエス、時にはノーになります。たとえば、からイテレータを取得する場合std::vector<int>、それがであるstd::vector<int>::iteratorか、auto iterator = ...;それで十分であることを知る必要がありますか?誰もがイテレーターでやりたいことはすべて、それがイテレーターであるという事実によって与えられます-タイプが具体的に何であるかは関係ありません。

autoこれらの状況で、コードが読みにくくならない場合に使用します。


12

個人的に私が使用するのautoは、プログラマにとってそれが何であるかが絶対に明らかな場合のみです。

例1

std::map <KeyClass, ValueClass> m;
// ...
auto I = m.find (something); // OK, find returns an iterator, everyone knows that

例2

MyClass myObj;
auto ret = myObj.FindRecord (something)// NOT OK, everyone needs to go and check what FindRecord returns

5
これは、悪い命名が読みやすさを損なうことの明確な例であり、実際には自動ではありません。「DoSomethingWeird」が何をするのか、誰も微妙な考えを持っているわけではないので、autoを使用しても、それを読みやすくすることはできません。どちらの方法でもドキュメントを確認する必要があります。
R.マルティーニョフェルナンデス

4
さて、今は多少良くなっています。それでも、変数の名前があまりよくないことに気付いたので、まだ痛いです。記述したauto record = myObj.FindRecord(something)場合、変数の型がレコードであることは明らかです。またはit、それと同様の名前を付けると、イテレータを返すことが明確になります。を使用しなかった場合でもauto、変数に適切な名前を付けると、関数のどこからでも型を調べるために宣言に戻る必要がないことに注意してください。この例は今では完全なストローマンではないため、私は下票を削除しましたが、ここではまだ議論を買いません。
R.マルティーニョフェルナンデス

2
@ R.MartinhoFernandesに追加する:問題は、「レコード」が正確に何であるかということです。:それは、私はそれが記録されていることがより重要なのは、実際の根本的なプリミティブ型は、別の抽象化層..ですので、1が自動ずに、おそらく持っていると思うですMyClass::RecordTy record = myObj.FindRecord (something)
paul23

2
@ paul23:autoとtypeを使用すると何が得られますか。もしあなたの唯一の異議が「これの使い方がわからない」だけなら。どちらのあなたはとにかくそれを調べることができます。
GManNickG

3
@GManNickGは、重要でないことの正確なタイプを教えてくれます。
paul23

10

この質問は意見を求めるものであり、それはプログラマーによって異なりますが、私はノーと言います。実際、多くの場合、その反対はauto、プログラマが細かい点ではなくロジックに集中できるようにすることで、コードを理解しやすくするのに役立ちます。

これは、複雑なテンプレートタイプの場合に特に当てはまります。これは、単純化された例です。どちらがわかりやすいですか?

for( std::map<std::pair<Foo,Bar>, std::pair<Baz, Bot>, std::less<BazBot>>::const_iterator it = things_.begin(); it != things_.end(); ++it )

.. または...

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

2番目の方が理解しやすいと言う人もいれば、最初の人が言う方もいます。さらに他の人は、を無償で使用autoすると、それを使用するプログラマーの口がきけないことに貢献するかもしれないと言うかもしれませんが、それは別の話です。


4
+1ハハ、誰もがstd::map例に加えて、複雑なテンプレート引数を提示しています。
ナワズ

1
@Nawaz:maps を使用すると、非常に長いテンプレート名を簡単に見つけることができます。:)
ジョンダイブリング

@Nawaz:私は誰も...より良く、より読みやすい代替として、forループベースの範囲で来ていない理由は、その後不思議
PlasmaHH

1
@PlasmaHH、イテレータを持つすべてのループを範囲ベースに置き換えることができるわけではありません。forたとえば、イテレータがループ本体で無効化されているため、事前にインクリメントするか、まったくインクリメントしない必要がある場合。
ジョナサンウェイクリー

@PlasmaHH:私の場合、MSVC10は範囲ベースのforループを行いません。MSVC10は私の頼りになるC ++ 11テストベッドなので、実際にはあまり経験がありません。
ジョンディブリング

8

これまでのところ多くの良い答えがありますが、元の質問に焦点を合わせるために、ハーブは彼のアドバイスでauto自由に使うには行き過ぎだと思います。あなたの例は、auto明らかに読みやすさを損なう1つのケースです。一部の人々は、変数にカーソルを合わせて型を見ることができる現代のIDEでは問題ではないと主張しますが、私は同意しません:常にIDEを使用する人でさえ、コードのスニペットを単独で見る必要がある場合があります(コードレビューのことを考えてください) 、例えば)、IDEは助けにはなりません。

結論:auto役立つ場合に使用します。つまり、forループの反復子です。読者がタイプを見つけるのに苦労するときは使用しないでください。


6

明確なタイプがない場合、オートが役立つことを誰もまだ指摘していないことに私は非常に驚いています。この場合、テンプレートで#defineまたはtypedefを使用して実際の使用可能なタイプを見つけることでこの問題を回避するか(これは簡単ではないこともあります)、または単にautoを使用します。

プラットフォーム固有のタイプを持つ何かを返す関数を取得したとします:

#ifdef PLATFROM1
__int256 getStuff();
#else //PLATFORM2
__int128 getStuff();
#endif

魔女の使用法を好むでしょうか?

#ifdef PLATFORM1
__int256 stuff = getStuff();
#else
__int128 stuff = getStuff();
#endif

または単に

auto stuff = getStuff();

確かに、あなたは書くことができます

#define StuffType (...)

同様にどこかで、しかし

StuffType stuff = getStuff();

実際にxの型についてもっと詳しく教えてください。そこから何が返されるかを伝えますが、それはまさにautoです。これは単に冗長です-「もの」はここに3回書き込まれます-これは私の意見では「自動」バージョンよりも読みにくくなります。


5
プラットフォーム固有のタイプを処理する正しい方法はtypedefそれらです。
cmaster

3

可読性は主観的です。状況を見て、何が最善かを判断する必要があります。

あなたが指摘したように、自動なしでは、長い宣言は多くの混乱を生む可能性があります。しかし、あなたが指摘したように、短い宣言は価値があるかもしれない型情報を削除することができます。

これに加えて、これも追加します。書き込み可能性ではなく、読みやすさを確認してください。簡単に記述できるコードは、一般に読みやすくありません。たとえば、私が書いていた場合、自動を好むでしょう。私が読んでいた場合、おそらくより長い宣言。

その後、一貫性があります。それはあなたにとってどれほど重要ですか?一部の部分でautoを使用し、他の部分で明示的な宣言を使用しますか、それとも一貫した1つのメソッドを使用しますか?


2

読みにくいコードの利点を利点として取り上げ、プログラマーがますますそれを使用することを奨励します。どうして?autoを使用するコードが読みにくい場合は、明らかに書くのも難しいでしょう。プログラマは、仕事を改善するために、意味のある変数名を使用せざるを得ません。
たぶん、プログラマーは意味のある変数名を書いていないかもしれません。しかし、最終的にはバグの修正中、またはコードレビュー中に、彼/彼女が他の人にコードを説明する必要がある場合、またはそれほど近い将来、保守担当者にコードを説明する場合、プログラマは間違いを認識し、将来の意味のある変数名。


2
せいぜい、あなたは変数名を書く人が好き取得したいmyComplexDerivedType不足しているタイプ、タイプの繰り返しによるクラッタコード(変数が使用されているすべての箇所)を補うために、そしてどの省略する人々を誘惑目的名前に変数のを。私の経験では、コードに障害物を積極的に入れるほど非生産的というものはありません。
cmaster

2

次の2つのガイドラインがあります。

  • 変数のタイプが明らかな場合、書くのが面倒、またはautoの使用を決定するのが難しい場合。

    auto range = 10.0f; // Obvious
    
    for (auto i = collection.cbegin(); i != cbegin(); ++i) // Tedious if collection type
    // is really long
    
    template <typename T> ... T t; auto result = t.get(); // Hard to determine as get()
    // might return various stuff
  • 特定の変換が必要な場合、または結果のタイプが明確ではなく、混乱を招く場合があります。

    class B : A {}; A* foo = new B(); // 'Convert'
    
    class Factory { public: int foo(); float bar(); }; int f = foo(); // Not obvious

0

はい。冗長性は低下しますが、一般的な誤解は、冗長性が読みやすさを低下させることです。これは、コードを解釈する実際の能力ではなく、読みやすさを美的であると考える場合にのみ当てはまります。これは、autoを使用しても増加しません。最も一般的に引用されている例であるベクトル反復子では、autoを使用するとコードの可読性が向上するように見えます。一方、autoキーワードが何を提供するかは必ずしもわかりません。内部再構築を行うには、コンパイラと同じ論理パスに従う必要があり、多くの場合、特にイテレータの場合、間違った仮定をすることになります。

結局、「自動」はコードの読みやすさと明快さを犠牲にします。これは、構文的で審美的な「クリーンさ」(イテレーターが不必要に複雑な構文を持っているためにのみ必要です)と、特定の行で入力する文字数を10個減らす能力のためです。リスクや長期的な努力に値するものではありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.