C++使用StringPiece减少string类的拷贝

  • 构造函数
  • 操作
  • 字符串比较
  • Traits
  • 参考链接

使用c++ string类不可避免会带来很多不必要的拷贝,拷贝多了必然影响性能。因此在很多高性能C++框架的实现中,都会使用StringPiece类作为string类的wrapper,该类只持有目标字符串的指针,而避免额外的拷贝,比较常见的实现有:

  1. muduo实际上是使用了pcre的StringPiece的实现
  2. Chromium

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_PREDICATE

Traits

由于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

参考链接

  1. google StringPiece
  2. muduo::StringPiece

C++使用StringPiece减少string类的拷贝相关推荐

  1. C++---string类接口整理与深浅拷贝

    string:是表示字符串序列的类,不能操作多字节或者变长字符序列 在使用string类时,必须包含#include头文件以及using namespace std; 常见的接口整理 常见的strin ...

  2. C++ String类写时拷贝 4

    http://blog.51cto.com/zgw285763054/1839752 维基百科: 写入时复制(英语:Copy-on-write,简称COW)是一种计算机程序设计领域的优化策略.其核心思 ...

  3. string类的写时拷贝

    由于浅拷贝使多个对象共用一块内存地址,调用析构函数时导致一块内存被多次释放,导致程序奔溃. 实现string类的时候通常显示的定义拷贝构造函数和运算符重载函数. 由于释放内存空间,开辟内存空间时花费时 ...

  4. string类的构造函数,拷贝构造函数,析构函数和赋值函数

    String 类的原型如下 class String { public: String(const char *str=NULL); //构造函数 String(const String &o ...

  5. C++ string类(包括深浅拷贝)

    目录 一.字符码表 一.为什么用string类 二.使用标准库中的string类 1.string类 2.string中的常用接口说明 (1)string类对象的常见构造 (2)string类对象访问 ...

  6. Java String类源码解析

    String直接继承Object 含有一个char[] value,还有一个int hash默认值为0 new String()的构造产生的是一个值为""的字符数组 String( ...

  7. String类、StringBuffer类、StringBuilder类的区别

    String是Java中基础且重要的类,并且String也是Immutable类的典型实现,被声明为final class,除了hash这个属性其它属性都声明为final,因为它的不可变性,所以例如拼 ...

  8. 内存分布malloc/calloc/realloc/free/new/delete、内存泄露、String模板、浅拷贝与深拷贝以及模拟string类的实现

    内存分布 一.C语言中的动态内存管理方式:malloc/calloc/realloc和free 1.malloc: 从堆上获得指定字节的内存空间,函数声明:void *malloc (int n); ...

  9. C++【STL】【string类的使用】

    目录 string类的常用接口说明 1. string类对象的常见构造 2. string类对象的容量操作 3. string类对象的访问及遍历操作 [LeetCode]反转字符串 string的迭代 ...

最新文章

  1. 码农技术炒股之路——抓取日线数据、计算均线和除权数据
  2. Windows Server 2008之三设置TCP/IP
  3. Zookeeper与paxos算法
  4. MVC是一种用于表示层设计的复合设计模式
  5. python上传文件到linux服务器_python上传大文件到服务器报错
  6. HTML5 获得canvas油漆环境
  7. Logistics模型预测银行贷款违约
  8. mysql 开发包 安装_mysql的zip包的安装方法
  9. 模式识别中常见概率符号公式的学习笔记 By Youki~
  10. Flash(as3.0) CScreen
  11. CH Round #72树洞[二分答案 DFSBFS]
  12. 一张纸厚度是多少毫米_一张纸对折后的厚度,有多可怕!——北京市第二十中学教科室“科技云课堂”(4)...
  13. php 中文日期转时间戳,php日期转时间戳,指定日期转换成时间戳
  14. python商城管理系统_【程序源代码】全端商城管理系统(后台+小程序)
  15. 经济学中的M0 M1 M2 M3的含义
  16. 《为何佛不显身制止战争?》
  17. matlab保存bln文件,气象万千(冯锦明课题组)-软件程序
  18. linux实训心得体会范文
  19. 深度学习笔记其五:卷积神经网络和PYTORCH
  20. 工程机械远程监控系统

热门文章

  1. 学计算机平面设计可以找什么工作,大学生学了平面设计之后能找什么样的工作...
  2. 线段树求区间和(单点更新)
  3. 如何使用Appverifier ?
  4. 破解SQLSERVER存储过程的加密
  5. STL中list用法详解
  6. Python中is和==有什么区别?
  7. 深入理解浏览器原理和架构|硬核
  8. 阿里技术专家:数据一致性检测的应用场景与最佳实践
  9. 多图 | 操作系统中,进程与线程怎么设计的?
  10. 动手实现一个 localcache - 设计篇