C/C++字符串处理之String

Table of Contents

概要

理解String(BasicString)

关于TempString基类

源码

参考阅 读

概要

我们知道,C++标准库(STL)提供了string(basic_string)类进行字符串操作。字符串很可能除了内存 分配器(allocator)1外使用最为频繁的STL类。但是C++社区对string的指责从来就没有停止过。

归纳起来,STL的 string类主要有以下这些争议点:

接口过多且规格和其他STL容器没有达成很好的一致性。例如,string::find使用下标 ,而不是以iterator作为迭代位置,这和其他容器不太一样。

内存碎片。由于过于频繁的字符串构造、析构,导致系统 的内存碎片现象严重。

Copy -On-Write与多线程安全。string(basic_string)基于Copy-On-Write技术的原因,是因为 string的赋值被设计成为低开销的。但是一旦考虑到多线程安全问题,Copy-On-Write会把大量的时间花在锁的开销上。一些新 的STL实现 (如SGI STL)放弃了基于Copy-On-Write的string实现。

我认同这些指责。字符串最好的设计,还是将 string分拆为一个常字符串(std::String)和一个字符串操作类(StringBuilder)。我们的StdExt库这样做了。

理解 String(BasicString)

StdExt的String(BasicString),和你以前见过的所有字符串类都不太一样。这个类比你想象 的还要简单,它只有两个成员变量:

template <class _E>
class BasicString
{
    const _E* m_pszBuf;
    size_t m_length;
};

它区别于string(basic_string)之处在于:

它是一个常字符串,它永远不会试图去篡改字符串内容 (m_pszBuf指向的数据)。

它没有析构,你可以认为其实只是一个结构体。当然,为了方便,BasicString还是有构造函 数。

它的m_pszBuf不以nil为结束。而是由m_length成员限定字符串的长度。

它不维护字符串内容(m_pszBuf) 的生命周期。如上所述,它没有析构,任何时刻它只是接受或者生成字符串内容,但是不负责销毁它。

最后一点非常重 要,也是它的特别之处:它并不维护字符串的生命周期。这可能让你诧异:居然会有这样字符串类,它并不管理字符串的生命周 期。

但是我们这样做了。而这的确给我们带来很多便利。例如:

赋值(复制)、子串(substr)是非常轻量的操 作。Copy-On-Write技术完全是多余的。

可以将任意的线性容器(如std::vector、std::basic_string)临时转换为 String(非常轻量)。参见下文中对String::cast方法的介绍。

为什么String类可以不管理自己的生命周期?这就是我 们StdExt的内存管理变革倡导的思想了。

浏览下String类的参考手册,你注意到有这样两个构造函数:

BasicString(const value_type* pszVal, size_type cch);

template <class AllocT>
BasicString(AllocT& alloc, const value_type* pszVal, size_type cch);

这表示:第一个构造函数传入 的pszVal,其生命周期比BasicString长(到BasicString析构时仍然有效)。而第二个构造函数的意思是,pszVal是一个临时有 效的字符串,这个构造函数将拷贝一个pszVal字符串的副本。

为什么不支持 BasicString(const value_type* pszVal) 这样的构造?

很简单,这个构造过于危险,我不能确定你的意图是什么。

关于TempString基类

从字面意 思来讲,这是一个临时字符串类。为什么它会是String(即BasicString)的基类?这其实只是实现上的需要。TempString理论 上就是String(只是有特殊的生命周期),和BasicString规格一致。之所以它最后成为BasicString的基类,完全是实现上方便 的考虑。

以BasicString::compare为例,我们考察以下这个函数:

int BasicString::compare(const TempString<_E> b) const;

这个函数的含义非常丰富。相当于定义了以下这一系列的函数:

int BasicString::compare(const _E& b) const; // 与包含单个字符b的字符串比较
int BasicString::compare(const _E* b) const; // 与C Style风格的字符串b比较
int BasicString::compare(const basic_string<_E>& b) const; // 与STL string比较
int BasicString::compare(const BasicString<_E>& b) const; // 与另一个常String比较
int BasicString::compare(const vector<_E>& b) const; // 与向量表示的字符串b比较
int BasicString::compare(const BasicStringBuilder<_E>& b) const;

一个函数可抵6个函数!

时间: 2024-09-19 10:08:27

C/C++字符串处理之String的相关文章

在类中使用string类的问题。我定义的构造函数,想把字符串赋给string对象,却实现不了。

问题描述 在类中使用string类的问题.我定义的构造函数,想把字符串赋给string对象,却实现不了. //12.2.ano.h #ifndef STRING2_H_ #define STRING2_H_ #include #include using std::string; using std::cout; using std::cin; using std::endl; class String { private : string str; public : String(); Str

字符串-关于C++ string 的问题

问题描述 关于C++ string 的问题 10C 实现C++ string中一个函数函数形式为replace(S1,i,jS2)S1是string对象,i表示从S1对象的i位置开始删除长度为j的字符串,并用S2替换这个字符串.能否给个思路? 解决方案 如果你要用数组的话,程序要满足一个条件,strlen(S2)=j-i;类似的程序,你可以参考写一下#include #include using namespace std; int main(){ string a;/////指定串,可根据要求

我为什么不能把从数据库读出来的字符串赋值给String的变量String str=rs.getString(&amp;amp;quot;name&amp;amp;quot;);

问题描述 我为什么不能把从数据库读出来的字符串赋值给String的变量Stringstr=rs.getString("name"):总是出错.但是能直接输出System.out.println(rs.getString("name"))急啊我在线等哪位帮我解决一下33XXXXXX! 解决方案 解决方案二:错误提示Exceptioninthread"main"java.sql.SQLException:afterendofresultset....

javascript正则表达式和字符串RegExp and String(一)_正则表达式

前言 正则表达式是javascript非常重要和常用的功能,在jquery等大型框架中用的非常频繁,最近抽时间学习了解了相关知识,记录下来与需要的朋友分享. 思维导图 RegExp(正则表达式)的创建方式 可以通过两种方式创建一个RegExp,具体如下: 通过/-./的方式来创建正则表达式(注意: /--/两边是没有单引号或双引号的) 通过RegExp构造方法来创建一正则表达式 为了更好的描述模式,正则表达式提供了3个标识,分别是: g/i/m g: 全局匹配:在整个字符串中匹配,而不是在第一次

C# 枚举类型转换字符串 Enum to string

c# 枚举类型转换字符串 enum to string 枚举类型都是值类型. system.enum是一个抽象类(abstract class),所有枚举类型都直接继承自它,当然也同时继承了它的所有成员. 所有的值类型都是system.valuetype的后代,枚举类型也不例外,枚举类型直接继承自system.enum,而system.enum却又直接继承自system.valuetype的,所以,枚举类型也是 system.valuetype的后代. 值类型都是system.valuetype

javascript正则表达式和字符串RegExp and String(二)_正则表达式

在上篇文章给大家介绍了javascript正则表达式和字符串RegExp and String(一),本文给大家继续分享相关内容. 前言 我认为,在学习一门编程语言的过程中,字符串.数组.容器是非常重要的部分,为了提高编程效率,我通常会对字符串.数组以及容器作深入的学习,详细了解相关特点及对应的API.这篇文章是针对javascript字符串学习写下的笔记,在此与需要的朋友分享. 思维导图 字符串的创建方式 字符串是javascript中的基本类型之一,它对应的类型是String,可以通过两种方

javascript正则表达式和字符串RegExp and String(二)

在上篇文章给大家介绍了javascript正则表达式和字符串RegExp and String(一),本文给大家继续分享相关内容. 前言 我认为,在学习一门编程语言的过程中,字符串.数组.容器是非常重要的部分,为了提高编程效率,我通常会对字符串.数组以及容器作深入的学习,详细了解相关特点及对应的API.这篇文章是针对javascript字符串学习写下的笔记,在此与需要的朋友分享. 思维导图 字符串的创建方式 字符串是javascript中的基本类型之一,它对应的类型是String,可以通过两种方

javascript正则表达式和字符串RegExp and String(一)

前言 正则表达式是javascript非常重要和常用的功能,在jquery等大型框架中用的非常频繁,最近抽时间学习了解了相关知识,记录下来与需要的朋友分享. 思维导图 RegExp(正则表达式)的创建方式 可以通过两种方式创建一个RegExp,具体如下: 通过/-./的方式来创建正则表达式(注意: /--/两边是没有单引号或双引号的) 通过RegExp构造方法来创建一正则表达式 为了更好的描述模式,正则表达式提供了3个标识,分别是: g/i/m g: 全局匹配:在整个字符串中匹配,而不是在第一次

C/C++字符串处理之String ADT

概要 字符串是什么?我们认为,与其说它是一个类,不如说它只是一个ADT(抽象数据类型). 目前C++中的 字符串类 目前广泛采用的C++字符串类有二:std::string(basic_string,由STL提供).CString(由MFC或者WTL提供 ).它们的实现非常类似,都是带引用计数的.基于线性数据结构的字符串.不过SGI STL的Rope打破了这个规矩.它采用了一 种基于树结构的组织方式来实现字符串. 如何理解字符串只是ADT? 我们知道,基于值的容器主要有: 动 态数组(std::