C++ 98 程式語言標準將 if、switch、while 與 for 述句的文法依序定義為:
if (condition) statementif (condition) statement else statementswitch (condition) statementwhile (condition) statementfor (for-init-statement conditionopt; expression) statement
其中,我們能在 condition 宣告一個變數[1],並使用此變數的數值控制執行流程。例如:
#include <cstdlib>
#include <ctime>
#include <iostream>
int main() {
std::srand(std::time(NULL));
if (int a = std::rand() % 2) {
std::cout << "then-block: a=" << a << std::endl;
} else {
std::cout << "else-block: a=" << a << std::endl;
}
switch (int a = std::rand() % 4) {
case 0:
case 2:
std::cout << "even: a=" << a << std::endl;
break;
case 1:
case 3:
std::cout << "odd: a=" << a << std::endl;
break;
}
while (int a = std::rand() % 5) {
std::cout << "while: a=" << a << std::endl;
}
for (int x = 5; int a = std::rand() % x; --x) {
std::cout << "for: a=" << a << " x=" << x << std::endl;
}
}
在 condition 宣告的變數的生命週期涵蓋整個述句(包含子述句)。舉例來說,上面例子中的 if 判斷式與下面程式碼相似:
int main() {
// ...
{
int a = std::rand() % 2;
if (a) {
std::cout << "then-block: a=" << a << std::endl;
} else {
std::cout << "else-block: a=" << a << std::endl;
}
}
// ...
}
不過兩者還是有細微的差異。如果在 condition 宣告變數,我們就不能在子述句宣告同名變數:
int main() {
// ...
if (int a = std::rand() % 2) {
int a = 10; // compilation error
} else {
int a = 5; // compilation error
}
}
C++ 17 程式語言標準讓 if 述句與 switch 述句能多一個初始化述句(init-statement):
if (init-statementopt condition) statementif (init-statementopt condition) statement else statementswitch (init-statementopt condition) statement
這讓我們能在宣告變數的時候使用「不同於變數本身的條件」來控制執行流程。例如:以下的範例我們使用 init-statement 宣告變數用以獲取 m.emplace("hello")
的回傳值,再使用 p.second
或 inserted
控制執行流程:
#include <iostream>
#include <set>
int main() {
std::set<std::string> m;
if (auto p = m.emplace("hello"); p.second) {
std::cout << "inserted item: " << *p.first << std::endl;
} else {
std::cout << "ignored repeated item: " << *p.first << std::endl;
}
if (auto &&[iter, inserted] = m.emplace("hello"); inserted) {
std::cout << "inserted item: " << *iter << std::endl;
} else {
std::cout << "ignored repeated item: " << *iter << std::endl;
}
}
這個寫法也能和 std::optional
結合:
#include <iostream>
#include <optional>
extern std::optional<int> get_some_value();
int main() {
if (auto opt = get_some_value(); !opt.has_value()) {
std::cout << "Failed to get value" << std::endl;
} else {
std::cout << "Got: " << *opt << std::endl;
}
}
甚至能與 std::scoped_lock
或者 std::lock_guard
結合:
#include <iostream>
#include <mutex>
int value = 0;
std::mutex value_mutex;
int main() {
if (std::scoped_lock l(value_mutex); value <= 5) {
++value;
} else {
--value;
}
if (std::lock_guard<std::mutex> l(value_mutex); value <= 5) {
++value;
} else {
--value;
}
std::cout << value << std::endl;
}