# Way to C++: 6. Exception Safe

# 前言

考慮以下函數:

```cpp
int Calculate(int n) {  
    int *arr1 = new int[n];  
    int *arr2 = new int[n];  
    delete[] arr1;  
    delete[] arr2;  
    return n+1;  
}
```

看起來很好，在一開始 new 的陣列在離開函數時都釋放掉了。

但是其實會有問題的: 假如在 arr2 new 的時候，記憶體不夠，那該行就會拋出 Exception，直接離開 Calculate 函數，這時 arr1 請求的記憶體就沒有被釋放。

# Exception Safe

Exception Safe 主要是在要求，在發生 Exception 時，整個 Process 仍然要是好的，具體來說會通常要求這兩項：

*   沒用到記憶體要被釋放
*   狀態要是好的
*   在 Catch Exception 後，要可以繼續執行下去

第一項就是指 new 的要被 delete ，開過的檔案要關閉 … 等。

第二項的狀態，可以舉個例子，假如有兩個變數，一個是陣列，另一個是陣列長度，在一個**好的狀態**下，紀錄陣列長度的變數必須要真的記錄著正確的數值。

第三項比較像是第一項和第二項的結果。

## 分級

分成三種:

*   基礎: 發生 Exception 後，狀態是好的，並且沒有 Memory Leak。
*   強: 發生 Exception 後，狀態回歸到操作前。
*   超級強: No Exception。

越強所需要的成本通常會越高。

# **例子**

## Copy-and-swap

在 copy assignment 通常會寫成這樣:

```cpp
Foo& Foo::operator=(const Foo& foo) {  
    Foo tmp(foo); // copy initial  
    std::swap(foo..., ...); // ...  
    return &this;  
}
```

主要是因為通常 copy 會需要獲取新的資源，而這種操作就有可能會發生 Exception (像是記憶體不夠…)

所以把會發生 Exception 留在前面，不會發生 Exception 的時候，才開始更動物件的狀態，這樣就可以保證發生 Exception 時，物件狀態仍然是好的(當然這裡更強: 不變)。
