天天看點

《C++程式設計風格(修訂版)》——2.5 動态記憶體的一緻性

本節書摘來自異步社群出版社《c++程式設計風格(修訂版)》一書中的第2章,第2.5節,作者:【美】tom cargill,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。

c++程式設計風格(修訂版)

在程式清單 2.2 的 string 類中仍然存在着一些問題和不一緻的地方。其中,在動态記憶體管理 上的不一緻性與我們在前面所看到的不一緻性是一樣的,都是嚴重的問題。對于所有動态配置設定的 記憶體,我們都需要回答兩個問題:首先,動态記憶體是不是足夠大以容納将要存儲的資訊?其次, 是不是所有的動态記憶體都是可回收的?

在預設構造函數中配置設定的字元數組肯定可以容納空字元串:

《C++程式設計風格(修訂版)》——2.5 動态記憶體的一緻性

這個構造函數所基于的假設是:在建立對象時将會為字元串配置設定記憶體,并且這個記憶體足以 容納在對象生存期内需要儲存的任意字元串。成員函數 assign() 與這個假設也是一緻的:

《C++程式設計風格(修訂版)》——2.5 動态記憶體的一緻性

在 assign() 中調用 strcpy() 對參數字元串進行拷貝時,并沒有考慮到目标字元數組的長度或 者大小。編寫客戶代碼的程式員必須保證——在建立對象時,無論調用的是哪個構造函數——在 構造函數中所建立的數組必須能夠容納在 assign() 中複制的任意字元串。

然而,在成員函數 concat() 中采用了一種不同的方法:在建立每個字元串時,總是動态地決 定所需數組的精确大小。函數 concat() 忽略了在建立 string 對象時已經配置設定好的字元數組,即使 這個已配置設定的數組是足夠大的:

《C++程式設計風格(修訂版)》——2.5 動态記憶體的一緻性

在 assign() 和 concat() 這兩個函數的表現行為上存在着不一緻性。它們的差別在于,在為 string

對象設定新值時,是否會動态配置設定字元數組:assing() 永遠不會配置設定,而 concat() 則總是會配置設定。

接口一緻性

上面哪種控制數組大小的方法是更好的?和許多軟體決策一樣,沒有哪種方法是絕對的“正 确”或者絕對的“錯誤”。這兩種方法都有各自的優點。保持在構造函數中配置設定的數組不變(assign() 中的做法)是一種高效的方法,因為在後續的操作中就無需再調用記憶體配置設定函數。對每個字元串 值都動态地決定數組的大小(concat() 中的做法)則是一種更安全的方法,因為這種方法杜絕了 數組的“越界”行為。

這兩種方法都可以用在類中,但我們隻能使用其中的一種,以保持類一緻性,而不應該将 這兩種方法混合使用。否則,在使用這個類時,程式員将不得不去了解在接口中不同操作之間的 不同約定。如果一個程式員隻使用過 concat(),并且知道了數組的大小是動态增長的,那麼他就 會假定 assign() 也是同樣的行為,是以,當在 assign() 中發生數組記憶體的越界問題時,他所感到 的沮喪應該是可以預見的。

類的接口定義應該是一緻的——避免産生困惑。

繼續閱讀