17

ウィキペディアの条件演算子に関する記事で、次のコード ブロックを見ました。

Vehicle new_vehicle = arg == 'B' ? bus      :
                      arg == 'A' ? airplane :
                      arg == 'T' ? train    :
                      arg == 'C' ? car      :
                      arg == 'H' ? horse    :
                      feet;

コードを少し変更しましたが、考え方は同じです。この条件演算子の使用は受け入れられると思いますか? if-コンストラクトよりもはるかに簡潔でありelse、スイッチを使用すると、まったく新しい一連のバグの可能性が確実に開かれます (失敗した人はいますか?)。また、if- elses andswitchは R 値として使用できないため、最初に変数を作成し、初期化してから、必要に応じて割り当てる必要があります。

私はこれが本当に好きですが、他の人がどう思うか疑問に思っています。

しかし、フォーマットは不可欠です。

編集:私はまだこれが好きです。switchしかし、「このために声明を出した」という人たちの気持ちは理解できます。わかりました、そうかもしれません。しかし、条件が を返す関数呼び出しである場合はどうboolでしょうか? または、スイッチを入れることができない他の何百万ものもの。

あなたは本当に巨大なチェーンが優れていると私に納得させようとしているのifですelseか?はい、条件演算子の使い方を知らないプログラマーはこれを理解できません。彼らはそれを使用する方法を学ぶ必要があります。それは難解ではありません。

4

21 に答える 21

33

私はこのタイプの構造を何度も使用してきました。適切にフォーマットされている限り (つまり、すべてが 1 行に収まっていないため、判読不能になっている)、問題はないと思います。

于 2009-12-16T21:06:05.457 に答える
31

スイッチを使用するのは、このような目的のために設計されたものだからです。はい、フォールスルー バグのリスクがありますが、このネストされた条件付きブロックは、他のプログラマーに誤解されるリスクがはるかに高くなります。

于 2009-12-16T21:05:24.223 に答える
14

これは、条件演算子の使用の好例です。私は C++、Java、および Perl で常にこの方法で使用しています。

于 2009-12-16T21:07:59.690 に答える
12

何も問題がないだけでなく、可能な限り簡潔かつ明確な方法で操作の意図を伝えます。

if else で置き換えるか、またはスイッチの構築では、スニペットが

"new_vehicle =  "

すべてのインスタンスで繰り返されます。これには、リーダーがすべての繰り返しインスタンスを読み取って、実際にすべてのインスタンスで同じであることを確認する必要があります..

于 2009-12-16T21:08:45.057 に答える
11

文字定数の周りに多くの空白があり、読みにくくなっています。比較を括弧で囲みます: (そして、行の最後の値を移動するかもしれません。)

Vehicle new_vehicle = (arg == 'B') ? bus      :
                      (arg == 'A') ? airplane :
                      (arg == 'T') ? train    :
                      (arg == 'C') ? car      :
                      (arg == 'H') ? horse    :
                                     feet;

では見栄えがします。

于 2009-12-16T23:27:35.867 に答える
11

それはいいですね。これは if-else-if はしごに似ていますが、より簡潔です。

于 2009-12-16T21:07:59.287 に答える
8

条件演算子のバージョンはクリーンでシンプルで、C や C++ を知っている人には何が起こっているのかすぐにわかります。もう 1 つの利点は、すぐに値を返すことです。つまり、初期化に入れることができます (この例のように)。

switch ステートメントはもっと不器用です。変数を宣言してから初期化する必要がありますが、それを回避できる場合、通常は悪い考えです。より多くのタイピングが必要になり、バグが入り込む場所が増えますnew_vehicle = foo; break;

このルックアップをここだけで行う場合は、条件付きバージョンをそこに置いておくと、何が起こっているかがすぐにわかるので便利です。複数回発生する場合は、何か変更があった場合に更新する場所が 1 つだけになるように、関数に入れることを検討してください (たとえば、馬車の場合は「R」、ヘリコプターの場合は「L」など)。

于 2009-12-16T21:37:47.853 に答える
5

純粋にスタイルの選択。あなたがここに提示したような小さなデータセットの場合、あなたのプログラミングチームがそのようなことで投げ出されない限り、私の本では問題ありません.

于 2009-12-16T21:20:46.893 に答える
5

スイッチはより明確であり、おそらくはるかに効率的です。コードレビューでこのようなコードを見たら心配になります。また、これは「条件演算子」です。これは、三項演算子のインスタンス (現在は C および C++ で唯一のものですが) です。

于 2009-12-16T21:08:11.503 に答える
3

特に気になりません。

それは実際には何も購入せず、何かをより明確にしません。これは、オペレーターのかなり非標準的な使用法です。

主な利点は、やや賢いことです。私は、賢くあるべきかなりの (外的) 理由がない限り、賢くは避けます。

于 2009-12-17T07:19:59.083 に答える
2

ウィキペディアの記事の C++ セクションをもう少し注意深く読んでください。演算子を使用することが唯一の選択肢であり、 or?:で置き換えることができないいくつかの状況を明示的にリストしています。if/elseswitch

一方で、見た目がきれいだからという理由だけでは使いません。

于 2009-12-16T21:40:39.760 に答える
1

純粋に実用的:

プラス: 3進シーケンスはより柔軟性があり、の制限を回避するためにswitch使用できます。他の演算子(<=、> =など)または文字列比較などの他のテストを使用できます。

x = IsEven(arg) ?  0 : 
    (arg < 0)   ? -1 : 1; // or whatever

また、スイッチがパフォーマンスのボトルネックであり、確率が不均一である場合は、最も可能性の高いテストを最初に実行するように強制できます(選択されていないパスの保証が評価されていないため)。

So-So switchステートメントとは異なり、順序は重要です(に固執しない限り==)。これは利点になる可能性がありますが、それ以外の点では、メンテナが概念に慣れていない場合や急いでいる場合に誤解を招く可能性があるスイッチに似ています。

多くの開発者は、詳細がわからないために恥ずかしがる可能性があります(どの用語が評価されますか、演算子の頻度は大丈夫ですか?)-ただし、開発者プールが十分に提示された例を把握できない場合は、三項演算子を禁止することによって解決できない問題。

マイナス それはそれほど一般的ではないswitchので、オプティマイザはそれを同じように扱わないかもしれません。オプティマイザーは、スイッチに最適な実装(テーブル、バイナリ検索、比較シーケンス、またはこれらの任意の組み合わせ)を選択することを知っています。オプティマイザーは、評価の順序を再調整することはできず、ここでテーブルルックアップをサポートする可能性は低くなります。

簡単に認識できるように適切なフォーマットが必要です(「?」と「:」を並べます)-タブを使用するとうまくいきません。

美学

数学表記に近い、その正確さと簡潔さのために私はそれが好きです。しかし、それはそれに対しても使用される可能性があります。それはあまり一般的ではなく、よりもろいので、おそらくコードレビューで眉をひそめるでしょう。

于 2009-12-16T22:38:36.683 に答える
1

比較のために、C++0x では、条件演算子または行外関数を使用せずに式を使用できます。

Vehicle new_vehicle = [&]() -> Vehicle {
    if (arg == 'B') return bus;
    if (arg == 'A') return airplane;
    if (arg == 'T') return train;
    if (arg == 'C') return car;
    if (arg == 'H') return horse;
    return feet;
}();

しかし、実際にはそれほど良くはありません。

于 2009-12-16T22:46:20.723 に答える
1

私の意見では、例が単純であるため、あなたが行ったことは受け入れられます。それぞれのケースでより多くのことを行っていた場合、このタイプの構成は急速に混乱する可能性があります。そのため、次のようにフォーマットされたスイッチまたはネストされた if then elses (あまり多くの場合がない場合) を好みます。

  if (A) {
      //Do A stuff
  }
  else if (B) {
      //Do B stuff
  }
  else if (C) {
      //Do C stuff
  }
  else {
      //Do default stuff
  }

それはコードの可読性に関するものであり、コードの保守性に役立ちます。1 行に複数の式が表示されるのが好きではないので、私は条件演算子の大ファンではありませんでした。デバッガーでコードをシングル ステップ実行する場合、条件演算子を理解するのが難しい場合があります。コードが単純であればあるほど、コードが何をしているかに集中しやすくなります。

于 2009-12-16T23:20:46.240 に答える
1

どうですか:

enum Vehicle { bus = 'B', airplane = 'A', train, car = 'C', horse = 'H', feet = 'F' };
...
new_vehicle = arg;

:-)、 ところで。

于 2009-12-17T01:05:16.453 に答える
1

コーディングする人にとっては便利だと思いますが、レビュアーにとっては理解しにくいでしょう。

「キープ・イット・シンプル・バディ」

于 2009-12-17T07:32:02.553 に答える
1

std::map何人かの人々は、または他の連想配列タイプを使用して仕事をする可能性についてすでに言及しています。これを 1 か所 (または数か所) だけで行う限り、代わりに通常の配列またはベクトルを使用することを検討してください。

Vehicle vehicles[CHAR_MAX];

// Initialization    
std::fill_n(vehicles, CHAR_MAX, feet);
vehicles['A'] = airplane;
vehicles['B'] = bus;
vehicles['C'] = car;
vehicles['H'] = horse;
vehicles['T'] = train;

// Use
Vehicle new_vehicle = vehicles[arg];

必要/使用するテーブル (同じタイプのオブジェクトを格納する) の数と、含まれるオブジェクト (この場合は車両) のサイズに応じて、これはstd::map. 多くのテーブルを作成している場合、または各オブジェクトが非常に大きい場合std::mapは、より合理的な代替手段になります。

std::map(またはなど) を使用すると、unordered_mapより多くのコードを使用してデータ ストレージを節約できます。これは逆になりますが、Vehicle が小さい (たとえば 4 バイト) 限り、上記のような 1 つのテーブルは通常、0.5 キロバイト程度を占めます。特定のコンパイラのコードがどのくらいの大きさになるかを正確に推測するのは困難ですstd::mapが、通常は 0.5 キロバイトより大きくなる可能性が高いため、このようなテーブルを 1 つだけ作成する場合はstd::map、純損失。

もちろん、入力として文字のみを扱っていることがわかっている場合は、テーブルのサイズをかなり小さくすることができます。

template <class T>
class letter_table { 
    static const int range = 'Z' - 'A';

    T table[range];
public:
    // ...
    T operator[](int index) {
        index -= 'A';
        assert(index<range);
        return table[index];
    }
};

std::map例の場合、これにより約 100 バイトのテーブルが得られます。通常は占有されるスペースに、かなりの数の 100 バイトのテーブルを作成できます。

于 2009-12-16T22:05:36.267 に答える
1

I've never seen anything written like this before. While it is clever and well-formatted, this seems like the perfect opportunity to use a dictionary/hashtable (assuming Vehicle is an enumeration, which is unclear).

于 2009-12-16T21:24:29.877 に答える