Cơ chế:
cpp
void openFile(const std::string& path) {
if (path.empty()) throw std::invalid_argument("path rỗng");
// ...
}
try {
openFile("");
} catch (const std::invalid_argument& e) {
std::cerr << "Lỗi: " << e.what();
} catch (const std::exception& e) {
std::cerr << "Exception chung: " << e.what();
} catch (...) {
std::cerr << "Exception không xác định";
}Stack unwinding: khi exception được throw, destructor của mọi object trên stack được gọi theo thứ tự ngược — đây là lý do RAII hoạt động ngay cả khi có exception.
noexcept: khai báo hàm không ném exception. Nếu vi phạm → std::terminate() được gọi.
cpp
void swap(int& a, int& b) noexcept { int t = a; a = b; b = t; }Move constructor/destructor nên noexcept để std::vector dùng move thay copy khi resize.
Mechanism:
cpp
void openFile(const std::string& path) {
if (path.empty()) throw std::invalid_argument("empty path");
// ...
}
try {
openFile("");
} catch (const std::invalid_argument& e) {
std::cerr << "Error: " << e.what();
} catch (const std::exception& e) {
std::cerr << "General exception: " << e.what();
} catch (...) {
std::cerr << "Unknown exception";
}Stack unwinding: when an exception is thrown, destructors for all stack objects run in reverse order — this is why RAII is exception-safe.
noexcept: declares that a function will not throw. If it does → std::terminate() is called.
cpp
void swap(int& a, int& b) noexcept { int t = a; a = b; b = t; }Move constructors/destructors should be noexcept so std::vector can use move instead of copy when resizing.