Flat Leon Works

アプリやゲームを作ってます。

【C++】条件演算子いろいろ

条件演算子のメリット

条件演算子はif文とは違い式なので、必ず結果を伴います。なのでif文とは違い、変数の初期化return文での値の返却などで使うことができます。またif文よりも記述がシンプルになるので楽に書くことができ、また読みやすくなります。

条件演算子の使いどころ

  • 変数の初期化、代入
  • return文
  • 関数の引数

このように条件により違う値を設定する場面で活躍します。

条件演算子ではなくif文を使うべきところ

  • 条件式や結果の式が複雑な場合
  • 処理を行わない場合があるとき(例:代入する場合としない場合があるときなど)

もちろん条件演算子ではなくif文を使うべきところはたくさんあります。使い分けましょう。

条件演算子を入れ子にする

条件演算子は入れ子にするととても読みづらくなりますが、書き方を工夫する一気に読みやすくなります。

// そのまま書くと、とても読みづらい
const char* say = strcmp( animal, "neko" ) == 0 ? "nyaa" : strcmp( animal, "inu"  ) == 0 ? "wan"  : strcmp( animal, "buta" ) == 0 ? "boo"  : "";
// 改行とインデントでとても読みやすくなる
const char* say = strcmp( animal, "neko" ) == 0 ? "nyaa" :
                  strcmp( animal, "inu"  ) == 0 ? "wan"  :
                  strcmp( animal, "buta" ) == 0 ? "boo"  : "";

また、if文で書くより記述量がだいぶ減るので楽です。

// if文バージョン
const char* say = "";
     if ( strcmp( animal, "neko" ) == 0 ){ say = "nyaa"; }
else if ( strcmp( animal, "inu"  ) == 0 ){ say = "wan"; }
else if ( strcmp( animal, "buta" ) == 0 ){ say = "boo"; }

ただし、2段以上の入れ子は複雑になりすぎるので絶対にやめておきましょう

const char* name2 = is_lower  ? name == "a" ? type == "1" ? "a1" :
                                              type == "2" ? "a2" : "aX" :
                                name == "b" ? type == "1" ? "b1" :
                                              type == "2" ? "b2" : "bX" :
                                name == "c" ? type == "1" ? "c1" :
                                              type == "2" ? "c2" : "cX" : "XX"
                              : name == "a" ? type == "1" ? "A1" :
                                              type == "2" ? "A2" : "aX" :
                                name == "b" ? type == "1" ? "B1" :
                                              type == "2" ? "B2" : "BX" :
                                name == "c" ? type == "1" ? "C1" :
                                              type == "2" ? "C2" : "CX" : "XX";

条件演算子の注意点

演算子の優先順序に気をつける

条件演算子は他の演算子と一緒にを使うと演算子の優先順序がわかりにくくなります。他の演算子と一緒に使う場合は優先順序を明確にするために、()でくくるようにしましょう。

// 条件式の結果に +1000 したいのか、偽の場合の式が 0 + 1000 なのかわかりずらい
true ? 10 : 0 + 1000;

// 条件式の結果に +1000 したい場合はこのように括弧でくくる
(true ? 10 : 0) + 1000;

// 偽の場合の式が 0 + 1000 の場合はこのように括弧でくくる
true ? 10 : (0 + 1000);

結果の型は同じである必要がある

条件演算子内の「真の場合の式」と「偽の場合の式」は、同じ型である必要があります。暗黙の型変換は行われるようですが、以下のような場合は型の不一致でコンパイルエラーになります。

class Base{};
class A : public Base {};
class B : public Base {};

int main() {
    A a;
    B b;
    bool useA = false;
    Base* p_base = useA ? &a : &b;
    return 0;
}

abともにBaseの派生クラスなのでBase*への暗黙の型変換が働いても良さそうですが、そこまではやってくれないようです。

Base* p_base = useA ? &a : (Base*)&b;

このようにどちらか一方を明示的にBase*へ変換すれば、もう一方は暗黙に変換されるのでコンパイルエラーを回避することができます。

三項演算子という呼び方

条件演算子三項演算子とも呼ばれます。これは項を3つ取るからなのですが、三項演算子という名前では何をする演算子なのかわからないので条件演算子と呼んだほうがいいと思います。

まとめ

条件演算子は適切につかえば、if文より素早く書くことができ、読みやすくもなる便利な演算子です。活用していきましょう。