1. Vấn đề nó giải quyết
Kết quả lookup hoặc parsed state thường chỉ cần tên trong một quyết định rẽ nhánh. Khai báo sớm làm tên rò ra scope rộng hơn và tách initialization khỏi test.
2. Kiến thức cần có
Compiler hỗ trợ C++17, được gọi với warning đầy đủ, cùng các bài trước theo thứ tự của khóa học.
Biết block scope, iterator, lookup của associative container cùng
ifvàswitchthường.
3. Ý tưởng cốt lõi
C++17 cho phép if (init; condition) và switch (init; condition). Tên được khởi tạo tồn tại trong các branch rồi bị hủy khi toàn statement kết thúc.
4. Cú pháp tối thiểu
if (auto it = scores.find("Ada"); it != scores.end()) {
use(it->second);
}5. Cách nó hoạt động
Lookup iterator được khởi tạo ngay trong header
ifrồi lập tức so sánh với map end.Iterator có trong cả hai branch nhưng không tồn tại sau statement, tránh vô tình dùng lại stale value.
Chương trình in
Ada: 91rồi classificationexcellent, tạo test oracle nhỏ để so sánh với dự đoán trước khi biên dịch.
6. Lỗi thường gặp
Initializer và condition dùng semicolon chứ không phải comma; tên được khởi tạo tồn tại cả trong
else.Build thành công chưa đủ; phải kiểm tra lifetime, ordering và error path.
7. Khi nào nên dùng
Nên dùng kỹ thuật này khi helper object chỉ thuộc về một conditional statement.
Nên chọn cách C++11/14 đơn giản hơn nếu quy tắc C++17 không cải thiện safety, độ rõ hoặc hiệu năng đã đo trên các toolchain phải hỗ trợ.
8. Ví dụ đơn giản
Map iterator được giới hạn trong if, còn bản sao score được giới hạn trong switch phân loại kết quả.
Mã mẫu hoàn chỉnh
Tệp mã nguồn
cpp17/09_if_switch_with_initializer/main.cpp
#include <iostream>
#include <map>
#include <string>
int main() {
const std::map<std::string, int> scores{{"Ada", 91}, {"Linus", 88}};
if (const auto it = scores.find("Ada"); it != scores.end()) {
std::cout << it->first << ": " << it->second << '\n';
switch (const int score = it->second; score / 10) {
case 10:
case 9:
std::cout << "excellent\n";
break;
default:
std::cout << "keep practicing\n";
}
}
}
9. Điều cần nhớ
Statement initializer giữ acquisition, test và destruction cùng nhau trong scope hẹp nhất.
Phải chọn rõ chế độ C++17; default của compiler mới hơn có thể che lỗi portability.
Warning và ví dụ xác định biến quy tắc ghi nhớ thành bằng chứng.
10. Câu hỏi tự kiểm tra
Dễ — if và switch với initializer giải quyết vấn đề chính nào?
Trung bình — Lookup iterator sống ở đâu, và có thể gọi tên nó sau
ifkhông?Khó — Destruction hoạt động thế nào khi initializer sở hữu lock dùng chung cho hai branch?