使用 RAII 讀取 buffer 字串

遇到要利用一塊不定長度 buffer 來取得字串的 function

通常都要三行以上去處理 buffer

auto len = GetTextLength();
char* ary = new char[len+1]();
GetText(ary, len);
std::string result = ary;
delete [] ary;
return result;

缺點:

  1. result = ary; 很有可能會 fail ,這樣你就 memory leaks 了。
  2. 花了一半的篇褔(六行中的三行(get len, new, delete)),在做 buffer 的建立工作,難以閱讀。

使用 RAII ,讓 buffer 的建立與釋放工作,交給 ctor 與 dtor

RAII
DynamicArray<char> ary(GetTextLength()+1);
GetText(ary.buffer(), ary.size()-1);
return ary.const_buffer();

優點:

  1. exception strong safe, 就算在 GetText 中 assign item 中 fail 丟出 exception, ary 內的 data 保證會被 delete。
  2. less temporary, 越少 temporary 就有越少的 conceptual complexty,也有越少的誤用風險。
  3. low level operations are hidden, 使用者無需知道 new/delete 的操作。
  4. less code lines and more readable, 跟上一點一樣,少了許多底層的操作,剩下的行數讓人輕易的知道,是要從 GetText 讀取 string ,更能表現出它真的想做的事情。

缺點:

  1. 你要知道 RAII。
  2. 你要知道寫一個 Memory handling 的小 class 。
DynamicArray 的簡單實作
template<typename T>
class DynamicArray
{public: 
    DynamicArray(std::size_t size): m_size(size), m_ary(new T[size]){};
    ~DynamicArray(){ delete [] m_ary; }
    std::size_t size() const{ return m_size; };
    T* buffer() { return m_ary; }
    const T* const_buffer() const { return m_ary; };
private:
  std::size_t m_size;
  T* m_ary;
};

使用 RAII + std::vector

using vector
std::vector<char> ary(GetTextLength()+1, '\0');
GetText( &(ary[0]), ary.size() );
return std::string(ary.begin(), ary.end());

C++ 標準提出保證說,vector 的記憶空間,一定是連續的,所以可以這樣用 first element 的位址,來當做是陣列的 head。

comments powered by Disqus