C++の三項演算子は、条件に応じて2つの式のうち、どちらか一方を評価するための演算子です。
正式には「条件演算子」と呼ばれます。
3つのオペランドを使用するため、一般には三項演算子とも呼ばれています。
三項演算子は、単純な条件分岐を短く記述したい場合に便利です。
特に、条件によって変数へ代入する値を切り替えたり、関数の戻り値を選んだりする処理に適しています。
C++の三項演算子の基本的な書き方
三項演算子は、次の形式で記述します。
条件式 ? 条件が真の場合の式 : 条件が偽の場合の式
条件式が真と判定された場合は、?の後ろにある式が評価されます。
条件式が偽と判定された場合は、:の後ろにある式が評価されます。
基本的な使用例
#include <iostream>
int main()
{
int age = 20;
const char* result =
age >= 18 ? "成人です" : "未成年です";
std::cout << result << '\n';
return 0;
}
実行結果は次のとおりです。
成人です
この例では、age >= 18が条件式です。
条件が真なので、"成人です"が選ばれます。
ageが18未満であれば、"未成年です"が選ばれます。
三項演算子は式として利用できる
三項演算子は、if文とは異なり「式」です。
そのため、変数の初期化、関数の戻り値、関数の引数、出力処理などに直接組み込めます。
if文との違い
ifは条件に応じて処理を分岐させる文です。
一方、三項演算子は、条件に応じて2つの式のうち一方を評価します。
例えば、次のコードでは条件に応じて変数の初期値を決定しています。
int maxValue = a > b ? a : b;
同じ処理をif文で記述すると、次のようになります。
int maxValue;
if (a > b)
{
maxValue = a;
}
else
{
maxValue = b;
}
単純に値を選択する処理であれば、三項演算子のほうが簡潔に記述できます。
三項演算子を変数の初期化に使う方法
三項演算子は、条件によって変数の初期値を切り替えたい場合に便利です。
大きい値を選ぶ例
#include <iostream>
int main()
{
int a = 10;
int b = 20;
int maxValue = a > b ? a : b;
std::cout << maxValue << '\n';
return 0;
}
実行結果は次のとおりです。
20
a > bが真であればaが選ばれます。
偽であればbが選ばれます。
const変数を初期化する例
三項演算子を使うと、条件に応じた値でconst変数を直接初期化できます。
const int maxValue = a > b ? a : b;
const変数は、基本的に宣言時に初期化する必要があります。
三項演算子を使用すれば、条件分岐を含む初期化を1つの式として記述できます。
三項演算子を出力処理に使う方法
三項演算子は、変数に代入せず、そのまま出力処理に組み込むこともできます。
偶数と奇数を判定する例
#include <iostream>
int main()
{
int number = 7;
std::cout
<< (number % 2 == 0 ? "偶数" : "奇数")
<< '\n';
return 0;
}
実行結果は次のとおりです。
奇数
number % 2 == 0が真であれば"偶数"、偽であれば"奇数"が出力されます。
出力時は三項演算子を括弧で囲む
出力処理の中で三項演算子を使う場合は、三項演算子全体を括弧で囲みます。
std::cout << (condition ? "OK" : "NG");
次のように括弧を省略してはいけません。
std::cout << condition ? "OK" : "NG";
このコードは、次のように解釈されます。
(std::cout << condition) ? "OK" : "NG";
<<演算子は三項演算子よりも優先順位が高いためです。
その結果、"OK"や"NG"ではなく、conditionの値が出力されます。
三項演算子で文字列を切り替える方法
三項演算子では、数値だけでなく文字列も切り替えられます。
std::stringを使用する例
#include <iostream>
#include <string>
int main()
{
bool isLoggedIn = true;
std::string message =
isLoggedIn
? "ログインしています"
: "ログインしていません";
std::cout << message << '\n';
return 0;
}
isLoggedInがtrueなので、"ログインしています"が選ばれます。
bool型は直接条件式にできる
条件式がbool型の場合は、その変数を直接記述できます。
isLoggedIn ? "ログイン中" : "ログアウト中"
次のように== trueを付けても間違いではありません。
isLoggedIn == true
? "ログイン中"
: "ログアウト中"
ただし、通常はisLoggedInだけで十分です。
文字列リテラルとautoの注意点
文字列リテラルを三項演算子で切り替え、autoで受け取ると、std::stringにはなりません。
const charポインタとして推論される例
auto message =
condition ? "成功" : "失敗";
この場合、messageは通常const char*型になります。
std::string型として扱いたい場合は、型を明示します。
#include <string>
std::string message =
condition ? "成功" : "失敗";
片方をstd::string型に変換する方法もあります。
auto message =
condition ? std::string("成功") : "失敗";
ただし、初心者にとっては代入先の型を明示する方法が分かりやすいでしょう。
三項演算子を関数の戻り値に使う方法
三項演算子は、関数のreturn文にも使用できます。
合否を判定する例
#include <iostream>
#include <string>
std::string checkScore(int score)
{
return score >= 60 ? "合格" : "不合格";
}
int main()
{
std::cout << checkScore(75) << '\n';
return 0;
}
scoreが60以上であれば"合格"を返します。
60未満であれば"不合格"を返します。
if文で記述した場合
同じ処理をif文で記述すると、次のようになります。
std::string checkScore(int score)
{
if (score >= 60)
{
return "合格";
}
else
{
return "不合格";
}
}
単純な値の選択であれば、三項演算子を使うと簡潔です。
処理が複雑になる場合は、if文を使用したほうが読みやすくなります。
三項演算子で計算結果を切り替える方法
三項演算子の第2式と第3式には、単純な値だけでなく計算式も記述できます。
会員価格を計算する例
#include <iostream>
int main()
{
int price = 1000;
bool isMember = true;
int finalPrice =
isMember ? price * 90 / 100 : price;
std::cout << finalPrice << '\n';
return 0;
}
この例では、会員の場合に価格を10%引きにしています。
isMemberが真であれば、price * 90 / 100が計算されます。
偽であれば、元のpriceが選ばれます。
整数除算による切り捨てに注意する
priceがint型の場合、計算結果も整数になります。
割り切れない場合は、小数部分が切り捨てられます。
小数を含む結果が必要な場合は、double型を使用できます。
double finalPrice =
isMember ? price * 0.9 : price;
ただし、実際の通貨計算では浮動小数点数の丸め誤差に注意が必要です。
金額を正確に扱いたい場合は、円や銭などの最小単位を整数で管理する方法もあります。
途中計算のオーバーフローに注意する
次の計算では、price * 90が先に実行されます。
price * 90 / 100
priceが非常に大きい場合、途中計算がint型の範囲を超える可能性があります。
より広い整数型で計算するなら、次のように記述できます。
long long finalPrice =
isMember ? price * 90LL / 100 : price;
三項演算子では片方の式だけが評価される
三項演算子では、第2式と第3式の両方が評価されるわけではありません。
条件に応じて選ばれた一方だけが評価されます。
ゼロ除算を避ける例
#include <iostream>
int main()
{
int denominator = 0;
int result =
denominator != 0
? 100 / denominator
: 0;
std::cout << result << '\n';
return 0;
}
denominatorは0なので、100 / denominatorは評価されません。
そのため、ゼロ除算は発生せず、resultには0が代入されます。
ただし、入力値の検証を三項演算子だけに依存するのではなく、プログラム全体で適切にチェックすることが重要です。
関数呼び出しも片方だけ実行される
次のコードでは、条件に応じてどちらか一方の関数だけが呼び出されます。
int result =
condition
? calculateA()
: calculateB();
conditionが真ならcalculateA()だけが呼ばれます。
偽ならcalculateB()だけが呼ばれます。
三項演算子で関数を呼び分ける方法
三項演算子の第2式と第3式には、戻り値がvoid型の関数も記述できます。
void関数を呼び分ける例
#include <iostream>
void showSuccess()
{
std::cout << "成功しました\n";
}
void showFailure()
{
std::cout << "失敗しました\n";
}
int main()
{
bool success = true;
success
? showSuccess()
: showFailure();
return 0;
}
このコードは正しく動作します。
successが真ならshowSuccess()が呼ばれます。
偽ならshowFailure()が呼ばれます。
処理の分岐にはif文が適することもある
関数を呼び分けるだけであれば、三項演算子でも記述できます。
ただし、処理を分岐させる目的では、if文のほうが意図を理解しやすい場合があります。
if (success)
{
showSuccess();
}
else
{
showFailure();
}
三項演算子は、値や結果を選択する場面で使うと読みやすくなります。
三項演算子の条件式で数値を使う方法
C++では、条件式が最初からbool型である必要はありません。
条件式は、文脈的にbool型へ変換されます。
整数を条件式にする例
#include <iostream>
int main()
{
int value = 5;
std::cout
<< (value ? "真" : "偽")
<< '\n';
return 0;
}
整数では、0が偽として扱われます。
0以外の値は真として扱われます。
この例ではvalueが5なので、"真"が出力されます。
比較式を明示すると読みやすい
数値を直接条件にすることはできますが、比較式を明示したほうが意図が分かりやすい場合があります。
std::cout
<< (value != 0 ? "真" : "偽")
<< '\n';
何を判定しているのかが明確になるため、可読性を重視する場合に適しています。
三項演算子の結果を左辺値として使う方法
C++の三項演算子は、条件によって選択された変数を代入先として使用できる場合があります。
選択された変数へ代入する例
#include <iostream>
int main()
{
int a = 10;
int b = 20;
bool selectA = true;
(selectA ? a : b) = 100;
std::cout << "a = " << a << '\n';
std::cout << "b = " << b << '\n';
return 0;
}
実行結果は次のとおりです。
a = 100
b = 20
selectAが真なので、aが選ばれます。
その結果、aに100が代入されます。
左辺値として使える条件
この書き方が可能なのは、aとbがどちらも同じ型の左辺値だからです。
条件演算子全体も左辺値になるため、代入先として使用できます。
次のコードはコンパイルできません。
bool condition = true;
int a = 10;
(condition ? a : 20) = 100;
20は代入可能な左辺値ではないためです。
このような書き方は分かりにくい場合があるため、可読性を優先するならif文を使用しましょう。
三項演算子と型の関係
三項演算子では、第2式と第3式の型から、式全体の型が決まります。
同じ型を指定する例
int value =
condition ? 10 : 20;
10と20はどちらもint型です。
そのため、式全体もint型になります。
異なる数値型を指定する例
auto value =
condition ? 10 : 20.5;
10はint型で、20.5はdouble型です。
この場合、通常は10がdouble型へ変換されます。
そのため、式全体の型とvalueの型はdoubleになります。
意図しない型変換を防ぐため、必要に応じて両方の型をそろえましょう。
double value =
condition ? 10.0 : 20.5;
互換性のない型は指定できない
次のコードでは、int型とstd::string型を1つの共通型として扱えないため、通常はコンパイルエラーになります。
int number = 10;
std::string text = "hello";
auto value =
condition ? number : text;
このような場合は、両方を共通の型へ変換するか、処理を分ける必要があります。
三項演算子を入れ子にする方法
三項演算子の中に、別の三項演算子を記述することもできます。
点数から評価を決める例
#include <iostream>
#include <string>
int main()
{
int score = 85;
std::string grade =
score >= 90 ? "A" :
score >= 80 ? "B" :
score >= 70 ? "C" : "D";
std::cout << grade << '\n';
return 0;
}
実行結果は次のとおりです。
B
三項演算子は右から左へグループ化されます。
このコードは、概念的には次のように解釈されます。
std::string grade =
score >= 90
? "A"
: (score >= 80
? "B"
: (score >= 70 ? "C" : "D"));
入れ子が深い場合はif文を使う
三項演算子を入れ子にすると、条件と結果の対応が分かりにくくなります。
複数の条件を扱う場合は、if文を使用したほうが読みやすいことがあります。
std::string grade;
if (score >= 90)
{
grade = "A";
}
else if (score >= 80)
{
grade = "B";
}
else if (score >= 70)
{
grade = "C";
}
else
{
grade = "D";
}
三項演算子を入れ子にする場合は、読み手がすぐ理解できる範囲にとどめましょう。
三項演算子の演算子優先順位
三項演算子は、多くの算術演算子や比較演算子よりも優先順位が低い演算子です。
複数の演算子を組み合わせる場合は、括弧を付けると意図が明確になります。
条件式を括弧で囲む例
int result =
(a > 0 && b > 0) ? a + b : 0;
この括弧がなくても文法上は正しく解釈されます。
ただし、条件の範囲が分かりやすくなるため、複雑な条件では括弧を付けるとよいでしょう。
第3式には代入式も記述できる
次のコードはC++では有効です。
bool condition = false;
int a = 10;
int b = 20;
condition ? a : b = 100;
これは、次のように解釈されます。
condition ? a : (b = 100);
conditionが偽なので、b = 100が実行されます。
ただし、このような書き方は非常に分かりにくいため、実務では避けたほうがよいでしょう。
if (!condition)
{
b = 100;
}
三項演算子を使うメリット
三項演算子には、コードを簡潔に記述できるという利点があります。
単純な条件分岐を短く書ける
int result =
condition ? 1 : 0;
単純に2つの値から一方を選ぶ処理であれば、if文よりも短く記述できます。
宣言と同時に初期化できる
const int maxValue =
a > b ? a : b;
条件に応じた値を、変数の宣言と同時に設定できます。
処理の意図を簡潔に表せる
「条件によってどちらかの値を選ぶ」という処理であれば、三項演算子を使うことで意図を簡潔に表現できます。
三項演算子を使うデメリット
三項演算子は便利ですが、使い方によっては可読性を低下させます。
式が長いと読みにくくなる
auto result =
complicatedCondition()
? calculateSpecialResult(value1, value2)
: calculateDefaultResult(value3, value4);
処理内容が複雑な場合は、if文に分けたほうが理解しやすいことがあります。
入れ子にすると対応関係が分かりにくい
int result =
a ? b ? 1 : 2 : c ? 3 : 4;
文法上は正しくても、どの条件と結果が対応しているのか分かりにくくなります。
副作用を含む処理には向かない
condition ? ++a : ++b;
このコードは動作しますが、値の選択ではなく変数の更新を目的としています。
処理が複雑になる場合は、if文を使ったほうが安全です。
if (condition)
{
++a;
}
else
{
++b;
}
三項演算子とif文の使い分け
三項演算子とif文は、処理内容に応じて使い分けることが重要です。
三項演算子が適している場面
三項演算子は、条件によって単純に値を選択する場面に適しています。
int maxValue =
a > b ? a : b;
次のような用途にも適しています。
std::string status =
isActive ? "有効" : "無効";
return score >= 60 ? "合格" : "不合格";
if文が適している場面
複数の文を実行する場合や、条件分岐が複雑な場合はif文が適しています。
if (user.isLoggedIn())
{
loadUserData();
showDashboard();
writeLog();
}
else
{
showLoginPage();
}
コードを短くすることよりも、読みやすさと保守しやすさを優先しましょう。
三項演算子の実用例
三項演算子は、さまざまな場面で使用できます。
正負を判定する
std::string sign =
number >= 0 ? "0以上" : "負の数";
デフォルト値を設定する
int displayedCount =
count > 0 ? count : 0;
ポインタがnullptrか確認する
const char* message =
ptr != nullptr
? "nullptrではない"
: "nullptr";
この判定で確認できるのは、ポインタがnullptrかどうかだけです。
ポインタが指すオブジェクトの寿命や、実際に安全に参照できるかどうかまでは保証されません。
最小値を選ぶ
int minValue =
a < b ? a : b;
ただし、単純な最小値を求める場合は、標準ライブラリのstd::minを使う方法もあります。
#include <algorithm>
int minValue = std::min(a, b);
最大値を選ぶ
int maxValue =
a > b ? a : b;
標準ライブラリのstd::maxも利用できます。
#include <algorithm>
int maxValue = std::max(a, b);
単純な最小値や最大値を求める処理では、標準ライブラリを使用したほうが意図が明確です。
絶対値を求める
int absoluteValue =
value >= 0 ? value : -value;
ただし、符号付き整数型の最小値は、同じ型で絶対値を表現できない場合があります。
例えば、int型の最小値に対して単純に符号を反転すると、型の表現範囲を超える可能性があります。
通常の絶対値計算には、標準ライブラリのstd::absも利用できます。
#include <cstdlib>
int absoluteValue = std::abs(value);
三項演算子でよくある間違い
三項演算子を使用する際は、構文や型、優先順位に注意が必要です。
コロンを書き忘れる
誤った例は次のとおりです。
int result =
condition ? 10;
三項演算子では、真の場合と偽の場合の両方を記述する必要があります。
正しくは次のとおりです。
int result =
condition ? 10 : 20;
出力時に括弧を付けない
誤った例は次のとおりです。
std::cout << condition ? "OK" : "NG";
正しくは、三項演算子全体を括弧で囲みます。
std::cout << (condition ? "OK" : "NG");
戻り値の型を意識しない
auto value =
condition ? 1 : 2.5;
この場合、valueはdouble型になります。
autoを使用していても、三項演算子全体の型を意識する必要があります。
複雑な処理を詰め込む
三項演算子の中に長い処理や複数の副作用を詰め込むと、コードが読みにくくなります。
複雑な条件分岐では、無理に1行へまとめず、if文へ分けましょう。
三項演算子のサンプルコード
次のコードでは、三項演算子を使って合否と評価を判定しています。
#include <iostream>
#include <string>
int main()
{
int score = 75;
std::string result =
score >= 60 ? "合格" : "不合格";
std::string grade =
score >= 90 ? "A" :
score >= 80 ? "B" :
score >= 70 ? "C" : "D";
std::cout << "結果: " << result << '\n';
std::cout << "評価: " << grade << '\n';
return 0;
}
実行結果は次のとおりです。
結果: 合格
評価: C
最初の三項演算子では、点数が60点以上かどうかを判定しています。
2つ目の三項演算子では、点数に応じて評価を決定しています。
評価区分が増えたり、判定処理が複雑になったりする場合は、if文や専用の関数へ分けると管理しやすくなります。
C++の三項演算子についてのまとめ
C++の三項演算子は、条件に応じて2つの式のうち一方を評価する演算子です。
基本構文は次のとおりです。
条件式 ? 条件が真の場合の式 : 条件が偽の場合の式
三項演算子は式なので、変数の初期化、関数の戻り値、出力処理、関数呼び出しなどに組み込めます。
また、第2式と第3式の両方が評価されるのではなく、条件によって選ばれた一方だけが評価されます。
単純に2つの値から一方を選ぶ処理では、三項演算子を使うとコードを簡潔にできます。
一方で、条件式や処理が長い場合、入れ子が深い場合、副作用を伴う場合には、可読性が低下します。
三項演算子は単純な値の選択に使用し、複雑な条件分岐にはif文を使用することが、読みやすく保守しやすいC++コードを書くための基本です。
以上、C++の三項演算子の書き方と使い方についてでした。
最後までお読みいただき、ありがとうございました。
