網站首頁 編程語言 正文
try-catch
在c++中,我們可以非常方便的使用try catch來捕獲異常
try {
throw 1;
} catch (int x) {
cout << "x " << x << endl;
throw std::runtime_error("exception");
} catch (...) {
cout << "exception" << endl;
}
你可能有時候 c++的try-catch沒什么用
但事實上,在解決某些問題方面,c++的異常強過你自己打flag 判斷 比如下面這個例子
void dep2() {
cout << "ok" << endl;
throw "error";
}
void dep1() {
dep2();
cout << "ok call dep2" << endl;
}
void func() {
dep1();
cout << "ok call dep1" << endl;
}
signed main() {
try {
func();
} catch (...) {
cout << "error" << endl;
}
return 0;
}
不使用try-catch 可以怎么寫?
pair<int, string> dep2() {
cout << "ok" << endl;
return {-1, "error"};
cout << "ret" << endl;
return {0, ""};
}
pair<int, string> dep1() {
auto[ret, err] = dep2();
if (ret == -1) return {ret, err};
cout << "ok call dep2" << endl;
return {0, ""};
}
pair<int, string> func() {
auto[ret, err] = dep1();
if (ret == -1) return {ret, err};
cout << "ok call dep1" << endl;
return {0, ""};
}
signed main() {
auto[ret, err] = func();
if (ret == -1) cout << err << endl;
return 0;
}
可以看出, try-catch還是可以幫助我們減少一些沒必要的判段和代碼
沒有try-catch的日子
上述是c++的。那么。。。c語言怎么辦呢? 那么,大抵是這樣的 用返回值來充當狀態碼返回,傳參留一個空位接受返回數據。
/**
* -1 error
* 0 ok
* other
**/
int func(int parameter, int* ret) {}
goto 是什么?
goto?語句允許把控制無條件轉移到同一函數內的被標記的語句在任何編程語言中,都不建議使用 goto 語句。因為它使得程序的控制流難以跟蹤,使程序難以理解和難以修改。任何使用 goto 語句的程序可以改寫成不需要使用 goto 語句的寫法。E.W.Dijikstra 在1965年提出結構化程序設計來規避這種錯誤
goto 就沒有他的優點的嗎?
goto是個好東西,就是得小心用。
現在的建議是不使用goto,且把goto妖魔化了
確實可以使用 while for之類的東西來替代goto
但是在有些時候,goto還是有一丟丟作用的。
例如:
signed main() {
for (int i = 1; i <= 1000; i++) {
for (int j = 1; j <= 1000; j++) {
for (int k = 1; k <= 1000; k++) {
if (i == 11 && j == 22 && k == 555)
goto end;
}
}
}
end:
return 0;
}
signed main() {
bool flag = true;
for (int i = 1; i <= 1000 && flag; i++) {
for (int j = 1; j <= 1000 && flag; j++) {
for (int k = 1; k <= 1000 && flag; k++) {
if (i == 11 && j == 22 && k == 555)
flag = false;
}
}
}
return 0;
}
拋開程序本身不談,有時候使用goto跳出多級循環的便利性,更勝一籌。
不同函數之間跳轉
上述講的goto只能在同一個函數內進行跳轉,不能夠跨函數跳轉
setjmp 和 longjmp
setjmp
setjmp()函數保存關于調用環境的各種信息(通常是堆棧指針、 緩沖區env中的指令指針,可能是其他寄存器的值和信號掩碼) 稍后由longjmp()使用。調用時,setjmp()返回0。(用man setjmp查看更詳細的介紹)
創建本地的jmp_buf緩沖區并且初始化,用于將來跳轉回此處。這個子程序保存程序的調用環境于env參數所指的緩沖區,env將被longjmp使用。如果是從setjmp直接調用返回,setjmp返回值為0。如果是從longjmp恢復的程序調用環境返回,setjmp返回非零值。
longjmp
在執行longjmp之時,傳入一個保存好的jmp_buf和一個返回值,程序就會切換上下文跨函數的跳轉到 之前設置的setjump處執行。
例子
jmp_buf env;
signed main() {
int stat = 0;
if ((stat = setjmp(env)) == 1) {
printf("1");
return 1;
}
printf("0");
longjmp(env, 1);
return 0;
}
// 結果:
>. 01
原理,進程是一個狀態機,我們當前的執行時刻擁有的狀態有 寄存器的值,pc指針,堆棧信息等。 和上下文切換一樣,我們可以保存一下當前進程的信息在jmp_buf里面,然后,等longjmp調用時,再去以保存的時候的進程信息去“切換”掉當前的狀態信息,實現了跳轉執行的過程,由于這個和上下文切換還是有區別,是切換回去當前進程。所以保存一下必要的寄存器值就可以了。
無try-catch的異常捕獲
利用宏替換和switch來匹配錯誤
可以簡單的實現異常的捕獲和跳轉
(還是c++的try-catch更強大)
#include <bits/stdc++.h>
#include <setjmp.h>
struct EXP {
jmp_buf buf;
int stat;
};
#define BEGIN_EXP(exp) switch (setjmp(exp.buf))
#define TRY(body) case 0: body break;
#define CATCH(exp, body) case exp: body break;
#define THROW(exp, data) longjmp(exp.buf, data)
int main() {
EXP exp;
BEGIN_EXP(exp) {
TRY({
std::cout << " data" << std::endl;
THROW(exp, 1);
})
CATCH(1, {
std::cout << "error 1" << std::endl;
THROW(exp, 2);
})
CATCH(2, {
std::cout << "error 2" << std::endl;
THROW(exp, 3);
})
CATCH(3, {
std::cout << "error 2" << std::endl;
})
}
return 0;
}
原文鏈接:https://juejin.cn/post/7133842387767394317
相關推薦
- 2022-09-08 pytorch中Tensor.to(device)和model.to(device)的區別及說明_p
- 2023-01-31 C#實現批量壓縮和解壓縮的示例代碼_C#教程
- 2021-12-13 C語言數據結構與算法之鏈表(二)_C 語言
- 2022-10-15 Go?Excelize?API源碼解讀GetSheetViewOptions與SetPageLayo
- 2022-05-10 IDEA中報錯 “Error running ‘Application‘: Command line
- 2023-01-30 python中用shutil.move移動文件或目錄的方法實例_python
- 2022-07-23 Python代碼實現雙鏈表_python
- 2021-12-22 Docker部署Microsoft?Sql?Server詳細步驟_docker
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支