在 C/C++ 中,异常是一种用来报告和处理错误的机制。它允许在错误发生时从当前代码跳出,并将控制权转移到一个专门的异常处理程序,以便处理错误。
1. C 语言异常处理
C 语言本身没有内置的异常处理机制,但可以通过以下方式模拟异常处理:
a. 错误码
通过函数的返回值或全局变量传递错误信息。
#include <stdio.h>
int divide(int a, int b, int *result) {
if(b==0) return -1; // 错误码:除以 0
*result = a / b;
return 0; // 成功码
}
int main() {
int result;
if(divide(10, 0, &result) == -1) {
printf("Error: Division by zero\n");
}
return 0;
}
b. setjmp
和 longjmp
C 提供的非局部跳转机制可以实现类似异常的行为,但使用复杂且不推荐。
#include <stdio.h>
#include <setjmp.h>
jmp_buf env;
void test() {
printf("Throwing exception\n");
longjmp(env, 1); // 跳转到 setjmp 的位置
}
int main() {
if(setjmp(env) == 0) {
test();
} else {
printf("Caught exception\n");
}
return 0;
}
2. C++ 异常处理
C++ 支持内置的异常处理,语法基于 try-catch
块。
a. 基本语法
#include <iostream>
void divide(int a, int b) {
if(b==0) {
throw std::runtime_error("Division by zero");
}
std::cout << "Result: " << a / b << std::endl;
}
int main() {
try {
divide(10, 0);
} catch (const std::exception& e) {
std::cerr << "Error:" << e.what() << std::endl;
}
return 0;
}
b. 自定义异常
可以继承 std::exception
来定义自己的异常类型:
#include <iostream>
#include <exception>
class MyException : public std::exception {
public:
const char* what() const noexception override {
return "My custom exception";
}
};
int main() {
try {
throw NyException();
} catch (const MyException& e) {
std::cout << "Caught: " << e.what() << std::endl;
}
return 0;
}
c. 多重捕获
根据异常类型捕获不同的异常:
#include <iostream>
int main() {
try {
throw 42; // 抛出一个整数异常
} catch (int e) {
std::cout << "Caught integer: " << e << std::endl;
} catch (...) {
std::cout << "Caught unknown exception" << std::endl;
}
return 0;
}
d. 异常传播
异常可以跨函数传播,直到被捕获:
#include <iostream>
#include <stdexcept>
void funcA() {
throw std::runtime_error("Error in funcA");
}
void funcB() {
funcA();
}
int main() {
try {
funcB();
} catch (const std::exception& e) {
std::cout << "Caught exception:" << e.what() << std::endl;
}
return 0;
}
3. 异常相关注意事项
a. noexcept 关键字
C++ 11 引入了 noexcept
,用于指定函数是否可能抛出异常。
void func() noexcept {
// 保证不会抛出异常
}
b. 异常安全性
确保在异常发生时,资源(如内存、文件句柄)能正确释放。可通过 RAII (资源获取即初始化)模式实现。
#include <iostream>
#include <memory>
void func() {
std::unique_ptr<int> p(new int(10)); // 自动释放
throw std::runtime_error("Error");
}
int main() {
try {
func();
} catch (const std::exception& e) {
std::cout << "Caught:" << e.what() << std::endl;
}
return 0;
}
c. 性能开销
C++ 异常的使用会增加代码大小,且运行时可能存在性能开销。应避免在性能敏感的代码中频繁抛出异常。
d. 不建议滥用异常
异常用于处理不可预期的错误,不应用于常规流程控制。
通过正确使用异常处理机制,可以提升程序的鲁棒性和可维护性。根据场景选择合适的策略(如 C 的错误码或 C++ 的
try-catch
)可以有效地管理错误。