高效操作字串的String Reference类

如下面的代码中一个函数接受一个std::string常量引用,在其函数内部需要使用std::string的一些函数操作字串。

void foo(const std::string& param) {
  ......
}

参数使用的是常量引用,如果传入一个std::string就不需要额外的拷贝。但是如果调用时传入的是一个字串常量,这时必然会生成一个std::string对象,并且会有一次内存拷贝。

关于字串发生拷贝可以使用下面的代码测试:

#include <string>
namespace {
const char* sString = "123456";

void foo(const std::string& str) {
  printf ("input string address: %x\n", str.c_str() );
}
}  // namespace

int main()
{
  printf("const string address: %x\n", sString);
  foo(sString);
  return 0;
}

这是一个很典型的问题,事实上只要不修改字串内容,并不需要另外复制一份。特别是对一些比较大的字串,避免拷贝对内存和性能都有极大的好处。于是Jeffrey Yasskin提出一个String reference : a non-owning reference to a string. 很多大型的项目都提供了各自的实现,包括Boost::StringRef, LLVM的StringRef, Chromium的base::StringPiece。

(STL也有字串的Copy-on-Write的实现,但要看实现版本。这里有更多的说明:std::string的Copy-on-Write:不如想象中美好。)

以下用StringPiece为例来介绍。它的原理也很简单,StringPiece内部仅持有字串指针和一个长度值,然后参照std::string的接口提供一组操作函数。比如find, find_first_of, rfind, substr. 

  template <typename STRING_TYPE> class BasicStringPiece {
 public:
  ......
  BasicStringPiece substr(size_type pos,
                          size_type n = BasicStringPiece::npos) const {
    return internal::substr(*this, pos, n);
  }

 protected:
  const value_type* ptr_;
  size_type     length_;
};
typedef BasicStringPiece<std::string> StringPiece;

它析构时不会释放字串,因为StringPiece不持有字串的所有权,也就是字串对象本身的生命周期一定要长于StringPiece对象。

可以看到StringPiece是一个模板类,主要是因为它需要同时支持以std::string和C string传递的参数。

以上面提供的取子串的操作为例,一个基本思路就是创建新的StringPiece, 把它的指针指到子串的起始位置,再将长度设定为子串的长度就可以了。在这个过程并没有出现字串的拷贝。

template<typename STR>
BasicStringPiece<STR> substrT(const BasicStringPiece<STR>& self,
                              size_t pos,
                              size_t n) {
  if (pos > self.size()) pos = self.size();
  if (n > self.size() - pos) n = self.size() - pos;
  return BasicStringPiece<STR>(self.data() + pos, n);
}

Enjoy it!

时间: 2024-09-21 01:04:11

高效操作字串的String Reference类的相关文章

C++语言基础-字串操作函数

如果你用过具有string数据类型的编程语言,你可能很不习惯,别人也有同感,所以标准C语言库中提供了几个字串操作函数.表1.3列出了最常用的字串操作函数及其用法说明.关于每个函数的详细说明和实例,见C++ Builder联机帮助. 表1.3字串操作函数 函数 说明 strcat() 将字串接合到目标字串的末尾 strcmp() 比较两个字串是否相等 strcmpi() 比较两个字串是否相等,不考虑大小写 strcpy() 将字串内容复制到目标字串中 strstr() 扫描字串中第一个出现的字串

java不变字串

请观察下述代码:   //: Stringer.java public class Stringer { static String upcase(String s) { return s.toUpperCase(); } public static void main(String[] args) { String q = new String("howdy"); System.out.println(q); // howdy String qq = upcase(q); Syste

java MD5算法返回数字型字串

算法   常有人问及MD5算法为何有些程序片断返回完全数字型结果而有些返回数字与字母的混合字串. 其实两种返回结果只是因为加密结果的不同显示形式,Blog中已经有.Net的实现,在此附加JAVA实现,供参考. JAVA的标准类库理论上功能也很强大,但由于虚拟机/运行时的实现太多,加之版本差异,有些代码在不同环境下运行会出现奇怪的异常结果,尤其以涉及字符集的操作为甚. package com.bee.framework.common; import java.security.MessageDig

Unicode控件的字串参数问题

控件|问题 写Unicode控件时发现的传字串参数的问题:问题描述:   Unicode的OCX,属性参数Text,类型:BSTR.   控件的源码(VC中)   afx_msg void SetText(LPCTSTR lpszText)    VB调用1:   Dim strTest As String    strTest = Text1.Text       'Text1文本框为空    If Not IsNull(strTest) Then       TestOCX2221.stri

JavaScript对象和字串之间的转换实例探讨_javascript技巧

JavaScript 对象定义方式 1. var obj = new Object() 复制代码 代码如下: <!--Add by oscar999--> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <TITLE> New Document </TITLE> <META NAME="Auth

io流-JAVA怎么从特定【行】开始读字串?

问题描述 JAVA怎么从特定[行]开始读字串? 就是JAVA随机读,不是按byte定位,按行数定位,最好还能获取该文件所有的行数,然后多线程split读取 解决方案 按行,你首先就要先找到对应的行,然后完成读Java 对文件的操作,你可以采用最基本的:一个字节一个字节读,然后判回车换行符,完成一行的读取.循环以上步骤,直到读到你想要行的数据. 解决方案二: 随机读写可以通过java.io.RandomAccessFile类.但是 你要按 行 读取,能不能 先做下预处理 记录下行. 解决方案三:

返回字串的拼音首字母

拼音 //////////////////////////////////////////////////////////////file://函数名:gf_getfirstletter(string)file://功能:返回字串的拼音首字母,支持混合字符串(可以包含非汉字)file://参数:as_inputstringfile://返回值:stringfile://created 大同 张和平 dtzhp@yeah.net///////////////////////////////////

PHP编程:探索字串的奥秘

编程 在许多Web编程里,字符串总是会被大量地生成和处理的.正确地使用和处理字符串,对于PHP程 序员来说也同样越来越重要了.本文从最简单的字符串定义一直引导你到高层字符串处理技巧,希望 对大家有所帮助. 一.引号定义字符串 在PHP中,通常一个字符串被定义在一对引号中,如: 'I am a string in single quotes' "I am a string in double quotes" PHP语法分析器是用成对的引号来判断一个字符串的.因此,所有字符串必须使用同一种

取得TextBox某一行的字串

这是使用EM_GETLINE message来做,比较奇特的是lParam是指向一个字串所在的位置,但是该字串传入时,前两个Byte要存该字串允许的最大长度. '以下在Form需一个TextBox,并设定MultiLine = True, 一个Command Button Private Sub Command1_Click() Dim str5 As String str5 = GetaLine(Text1,1) '取得第二行的字串,以0为基底 End Sub '以下在.Bas Option