ภาพรวม
C++17 เพิ่มฟีเจอร์ Init-Statements ให้กับ if, else, และ switch ช่วยจำกัด Scope ของตัวแปรและทำโค้ดสะอาดขึ้น
If-Else with Initializer
Syntax
if (init-statement; condition) {
// ...
} else {
// ...
}
ตัวอย่าง: ก่อน C++17 vs หลัง C++17
// Before C++17
{
int val = foo();
if (val > 0) { /* ... */ }
else { /* ... */ }
} // val ยังคงอยู่ใน Scope นี้
// C++17 - Init Statement
if (int val = foo(); val > 0) {
// ...
} else {
// ...
} // val หายไปแล้ว (Scope จบที่ if-else)
// สามารถใช้ชื่อตัวแปรซ้ำได้ใน Block ถัดไป
if (auto val = bar(); val > 0) { /* ... */ }
else { /* ... */ }
// val ตัวนี้คนละตัวกับด้านบน
Switch with Initializer
Syntax
switch (init-statement; variable) {
case ...: ...
}
ตัวอย่าง
switch (int val = rand() % 100; val) {
case 0: cout << "Zero"; break;
default: cout << "Non-zero: " << val; break;
}
// val Scope จำกัดใน Switch Block เท่านั้น
โค้ดตัวอย่างสมบูรณ์
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <map>
#include <string>
using namespace std;
// Mock function
int getDeviceStatus(int id) {
static map<int, int> status = {{1, 200}, {2, 404}, {3, 500}};
return status[id];
}
int main() {
srand(time(nullptr));
// If with Init - Scope Limited
if (int status = getDeviceStatus(1); status == 200) {
cout << "Device 1: OK (" << status << ")\n";
} else {
cout << "Device 1: Error (" << status << ")\n";
}
// Switch with Init
switch (int deviceId = rand() % 3 + 1; int status = getDeviceStatus(deviceId); status) {
case 200: cout << "Device " << deviceId << ": Online\n"; break;
case 404: cout << "Device " << deviceId << ": Not Found\n"; break;
case 500: cout << "Device " << deviceId << ": Server Error\n"; break;
default: cout << "Device " << deviceId << ": Unknown (" << status << ")\n";
}
// Reuse variable name in another block
if (auto val = 42; val > 0) {
cout << "First block: " << val << endl;
}
if (auto val = 3.14; val > 3.0) { // Different type, same name OK
cout << "Second block: " << val << endl;
}
return 0;
}
ผลลัพธ์ (ตัวอย่าง)
Device 1: OK (200)
Device 2: Not Found
First block: 42
Second block: 3.14
ประโยชน์หลัก
- Scope Safety: ตัวแปรหายทันทีหลัง Block ลด Bugs จากการใช้ตัวแปรเก่า
- Name Reuse: ใช้ชื่อตัวแปรซ้ำได้ใน Block ถัดไป
- Readability: Declaration และ Condition อยู่ที่เดียว
- Performance: ไม่ต้อง Declare ภายนอก Loop/Block
ข้อจำกัด
- Init-statement ต้องเป็น Declaration หรือ Expression Statement เท่านั้น
- ไม่สามารถใช้ Structured Binding ใน Init Statement ได้ (C++17)
- C++20: ใช้ได้ใน Range-based For:
for (auto [k, v] : map) ...
สรุป Syntax ใหม่ C++17
| Construct | Syntax |
|---|---|
| If | if (init; cond) ... else ... |
| Switch | switch (init; var) { case ... } |
| For (C++20) | for (init; cond; inc) ... (มีอยู่แล้ว) |
| While | ไม่รองรับ (ใช้ Block แยก) |