if-else ステートメントは、条件分岐を制御します。
if-branch内のステートメントは、conditionが 0 以外の値 (またはtrue) に評価された場合にのみ実行されます。
conditionの値が 0 以外の場合は、次のステートメントが実行され、省略可能なelseの後のステートメントはスキップされます。 それ以外の場合、次のステートメントはスキップされ、 else がある場合は、 else の後のステートメントが実行されます。
condition 0 以外と評価される式は次のとおりです。
true- null 以外のポインター
- 0 以外の算術値、または
- 算術型、ブール型、またはポインター型への明確な変換を定義するクラス型。 (変換の詳細については、「 標準変換」を参照してください)。
構文
init-statement:
expression-statement
simple-declaration
condition:
expression
attribute-specifier-seq
選ぶdecl-specifier-seqdeclaratorbrace-or-equal-initializer
statement:
expression-statement
compound-statement
expression-statement:
expression
選ぶ;
compound-statement:
{
statement-seq
選ぶ}
statement-seq:
statement
statement-seq
statement
if-branch:
statement
else-branch:
statement
selection-statement:
if
constexpr
opt17(init-statementopt17condition)if-branch
if
constexpr
opt17(init-statementopt17condition)if-branchelseelse-branch
17 この省略可能な要素は、C++17 以降で使用できます。
if-else ステートメント
if ステートメントのすべての形式で、構造体を除く任意の値を持つconditionが、すべての副作用を含めて評価されます。 実行されたif-branchまたはelse-branchにbreak、continue、またはgotoが含まれている場合を除き、ifステートメントからプログラム内の次のステートメントに制御が渡されます。
if...else ステートメントのelse句は、対応する else ステートメントを持たない同じスコープ内の最も近い前のif ステートメントに関連付けられています。
例
このサンプル コードでは、elseの有無にかかわらず、使用中のいくつかのif ステートメントを示します。
// if_else_statement.cpp
#include <iostream>
using namespace std;
int main()
{
int x = 10;
if (x < 11)
{
cout << "x < 11 is true!\n"; // executed
}
else
{
cout << "x < 11 is false!\n"; // not executed
}
// no else statement
bool flag = false;
if (flag == true)
{
x = 100; // not executed
}
int *p = new int(25);
if (p)
{
cout << *p << "\n"; // outputs 25
}
else
{
cout << "p is null!\n"; // executed if memory allocation fails
}
}
アウトプット:
x < 11 is true!
25
初期化子を持つ if ステートメント
C++17 以降、 if ステートメントには、名前付き変数を宣言して初期化する init-statement 式も含まれる場合があります。 if ステートメントのスコープ内でのみ変数が必要な場合は、この形式の if ステートメントを使用します。
Microsoft 固有: このフォームは Visual Studio 2017 バージョン 15.3 以降で使用でき、少なくとも /std:c++17 コンパイラ オプションが必要です。
例
// Compile with /std:c++17
#include <iostream>
#include <mutex>
#include <map>
#include <string>
#include <algorithm>
using namespace std;
map<int, string> m{ {1, "one"}, {2, "two"}, {10,"ten"} };
mutex mx;
bool shared_flag = true; // guarded by mx
int getValue() { return 42; }
int main()
{
if (auto it = m.find(10); it != m.end())
{
cout << it->second << "\n";
}
if (int x = getValue(); x == 42)
{
cout << "x is 42\n";
}
if (lock_guard<mutex> lock(mx); shared_flag)
{
cout << "setting shared_flag to false\n";
shared_flag = false;
}
string s{ "if" };
if (auto keywords = { "if", "for", "while" }; any_of(keywords.begin(), keywords.end(), [&s](const char* kw) { return s == kw; }))
{
cout << "Error! Token must not be a keyword\n";
}
}
アウトプット:
ten
x is 42
setting shared_flag to false
Error! Token must not be a keyword
constexpr ステートメントの場合
C++17 以降では、関数テンプレートで if constexpr ステートメントを使用して、複数の関数オーバーロードに頼ることなくコンパイル時の分岐の決定を行うことができます。
Microsoft 固有: このフォームは Visual Studio 2017 バージョン 15.3 以降で使用でき、少なくとも /std:c++17 コンパイラ オプションが必要です。
例
この例では、送信された型に基づいてテンプレートを条件付きでコンパイルする方法を示します。
// Compile with /std:c++17
#include <iostream>
template<typename T>
auto Show(T t)
{
//if (std::is_pointer_v<T>) // Show(a) results in compiler error for return *t. Show(b) results in compiler error for return t.
if constexpr (std::is_pointer_v<T>) // This statement goes away for Show(a)
{
return *t;
}
else
{
return t;
}
}
int main()
{
int a = 42;
int* pB = &a;
std::cout << Show(a) << "\n"; // prints "42"
std::cout << Show(pB) << "\n"; // prints "42"
}
if constexpr ステートメントはコンパイル時に評価され、コンパイラは関数テンプレートに送信された引数の型と一致するif ブランチのコードのみを生成します。
if constexpr ステートメントをコメントアウトし、if ステートメントのコメントを解除すると、コンパイラは両方の分岐のコードを生成します。 つまり、次のエラーが発生します。
-
ShowValue(a);を呼び出すと、ifステートメントが false で、コードが実行されない場合でも、tがポインターでないため、return *tでエラーが発生します。 -
ShowValue(pB);を呼び出すと、ifステートメントが true でコードが実行されていなくても、tがポインターであるため、return tでエラーが発生します。
if constexprを使用すると、関数テンプレートに送信された引数の型に一致するステートメントのみがコンパイルされるため、この問題は解決されます。
アウトプット:
42
42