C++使用StringPiece减少string类的拷贝
生活随笔
收集整理的這篇文章主要介紹了
C++使用StringPiece减少string类的拷贝
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
C++使用StringPiece減少string類的拷貝
- 構造函數
- 操作
- 字符串比較
- Traits
- 參考鏈接
使用c++ string類不可避免會帶來很多不必要的拷貝,拷貝多了必然影響性能。因此在很多高性能C++框架的實現中,都會使用StringPiece類作為string類的wrapper,該類只持有目標字符串的指針,而避免額外的拷貝,比較常見的實現有:
Chromium也說明了引入StringPiece的意義,主要是為了免拷貝:
// You can use StringPiece as a function or method parameter. A StringPiece // parameter can receive a double-quoted string literal argument, a "const // char*" argument, a string argument, or a StringPiece argument with no data // copying. Systematic use of StringPiece for arguments reduces data // copies and strlen() calls.pcre中也說明了StringPiece的使用注意事項
// ------------------------------------------------------------------ // Functions used to create STL containers that use StringPiece // Remember that a StringPiece's lifetime had better be less than // that of the underlying string or char*. If it is not, then you // cannot safely store a StringPiece into an STL container // ------------------------------------------------------------------下面我們以muduo源碼為例,講解StringPiece的實現
構造函數
由于StringPiece不控制字符串的生命周期,因為調用方要保證在StringPiece的生命周期里,其指向的字符串始終有效
注意字符串的頭指針ptr_被定義為const類型,其不允許任何修改
class StringPiece {private:const char *ptr_;int length_;public:// We provide non-explicit singleton constructors so users can pass// in a "const char*" or a "string" wherever a "StringPiece" is// expected.StringPiece() : ptr_(NULL), length_(0) {}StringPiece(const char *str): ptr_(str), length_(static_cast<int>(strlen(ptr_))) {}StringPiece(const unsigned char *str): ptr_(reinterpret_cast<const char *>(str)),length_(static_cast<int>(strlen(ptr_))) {}StringPiece(const std::string &str): ptr_(str.data()), length_(static_cast<int>(str.size())) {}StringPiece(const char *offset, int len) : ptr_(offset), length_(len) {} ... };操作
由于StringPiece不控制字符串的生命周期,因此字符串操作都是常數時間復雜度。
void clear() {ptr_ = NULL;length_ = 0; } void set(const char *buffer, int len) {ptr_ = buffer;length_ = len; } void set(const char *str) {ptr_ = str;length_ = static_cast<int>(strlen(str)); } void set(const void *buffer, int len) {ptr_ = reinterpret_cast<const char *>(buffer);length_ = len; }char operator[](int i) const { return ptr_[i]; }void remove_prefix(int n) {ptr_ += n;length_ -= n; }void remove_suffix(int n) { length_ -= n; }另外如果想使用StringPiece作為key使用hashmap,記得自定義哈希函數,這點可以查看Chromium的實現。
字符串比較
字符串的字典序比較,在==和!=這兩種比較中,調用memcmp比較到不相等的那一位為止
其他類型的比較中,按照短的長度進行比較,然后再根據需要的比較符號做判斷
bool operator==(const StringPiece &x) const {return ((length_ == x.length_) && (memcmp(ptr_, x.ptr_, length_) == 0)); } bool operator!=(const StringPiece &x) const { return !(*this == x); }#define STRINGPIECE_BINARY_PREDICATE(cmp, auxcmp) \ bool operator cmp(const StringPiece &x) const { \int r = memcmp(ptr_, x.ptr_, length_ < x.length_ ? length_ : x.length_); \return ((r auxcmp 0) || ((r == 0) && (length_ cmp x.length_))); \ } STRINGPIECE_BINARY_PREDICATE(<, < ); STRINGPIECE_BINARY_PREDICATE(<=, < ); STRINGPIECE_BINARY_PREDICATE(>=, > ); STRINGPIECE_BINARY_PREDICATE(>, > ); #undef STRINGPIECE_BINARY_PREDICATETraits
由于StringPiece只持有目標指針,所以是POD類型,并且擁有平凡構造函數,所以可以定義如下的type traits以指示STL采用更為高效的算法實現。
#ifdef HAVE_TYPE_TRAITS // This makes vector<StringPiece> really fast for some STL implementations template <> struct __type_traits<base::StringPiece> {typedef __true_type has_trivial_default_constructor;typedef __true_type has_trivial_copy_constructor;typedef __true_type has_trivial_assignment_operator;typedef __true_type has_trivial_destructor;typedef __true_type is_POD_type; }; #endif參考鏈接
總結
以上是生活随笔為你收集整理的C++使用StringPiece减少string类的拷贝的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BoltDB 源码分析
- 下一篇: C++右值引用和完美转发