回覆列表
  • 1 # 有緣書匯

    const char* 和 std::string 哪個好,要看場合。 假如是 C++ 的內部類實現,優先採用 std::string,可以減少很多記憶體分配釋放的麻煩。但假如是預先編譯庫的介面,提供給其他人使用,應該是封裝成 C 的介面,使用 const char*。 使用 C++ 風格實現,封裝成 C 風格的介面。 C++ 沒有二進位制標準。物件的二進位制佈局、連結名字、記憶體分配釋放,每個編譯器和標準庫都有不同。假如一種編譯器編譯出庫,匯出 C++ 介面,在另一種編譯器去使用,就算連結透過,執行時也可能出一些詭異的問題。不同編譯器並非特指 gcc 或者 vc 完全不同種類。有時是同一個 vc 編譯器,但是不同版本混用,也會出問題。甚至同一個版本的同一個編譯器,Release 選項編譯出來的庫,在 Debug 選項中使用,還是會出問題。 為了避免這些問題,預先編譯的庫,無論內部實現是否使用 C++,通常會匯出 C 風格的介面。假如你的 C++ 庫是直接提供原始碼,不用預先編譯,將原始碼嵌入到使用者工程,這時匯出 C++ 的類也沒有所謂。 題目中說 “在 C++ 程式設計中,領導堅持用 char 而不用 string”,缺少特定的背景,不能直接判斷領導的做法是否正確。

    評論問,C 風格返回的 char* 誰來釋放?在此補充說明。 原則上,記憶體是誰分配,就誰來釋放,有時也可變通。有多種方法,究竟哪種更好需要根據場合判斷。 知道最大值有時,在呼叫介面前就知道記憶體最大值。可以類似這樣寫 在呼叫之前,已經預知路徑的最大長度。傳入 buf 和 bufsize, 函式內部對資料進行填充。這樣根本就不需要動態分配 char*, 也就沒有釋放問題。 C 字串最後會填充一個 0。有時這種風格的介面,第二個引數並非 bufsize,而是字串的最大長度 max_str_len。當同一個工程使用多個庫時,它們的含義可能不同,很容易弄混。因而很多人會多新增一個位元組。 這種介面可以返回錯誤碼。假如根本不會發生錯誤,有時返回 const char*, 方便連鎖呼叫,比如 也可以將其封裝成結構,比如 不知道最大值不知道最大值時,就只能動態分配了。一種風格是讓使用者呼叫兩次,比如 在呼叫之前,還不知道最終長度。於是使用者先使用 NULL 呼叫一次 getTitle(NULL, 0),返回需要的記憶體大小。之後根據大小動態分配記憶體,這時記憶體的分配和釋放都交給了使用者。這種風格挺常見的,通常需要兩次呼叫。 這種風格,返回的 int 有多個含義,通常返回負數表示失敗。 另一種可選的風格是,庫內部臨時管理記憶體,使用者訪問結果。假如要將結果儲存下來以後使用,使用者就自己分配記憶體複製。比如 這種風格中,會先有更高一層,類似 context 的東西, 在裡面管理返回的 char*。每次 decode 的結果,都先放到庫自己管理的記憶體中,之後呼叫 getResult 獲取。於是同一個記憶體,可在多次 decode 中複用。每呼叫一次 decode, 會將之前的結果沖掉。在釋放 context 的時候,再釋放 char*。 假如嫌上面兩種風格麻煩,還可以在介面中註明,讓使用者自己釋放,比如: 這樣呼叫夠簡單,但貌似違背了誰分配,誰釋放的原則。但稍微變通一下,將原則理解成,誰用這函式誰釋放。 特別注意,雖然 base64_free 中只調用了 free,但也需要特別提供這個函式。不能讓使用者寫成 因為庫編譯時 malloc、free,跟使用者程式碼中的 malloc、free 有可能不同。而 malloc、free 需要嚴格匹配。 用 base64_free 包裝著 free, 放到庫的 .c 中編譯,這時的 free 就是庫編譯時的 free。但假如讓使用者自己呼叫 free,就是使用者程式碼中的 free,有可能跟 base64 庫中使用的 malloc 不匹配。

  • 中秋節和大豐收的關聯?
  • 雞毛菜重茬出現苗黃,乾枯是怎麼回事?