C++string类

本文详细介绍了C++中的string类,包括为何要学习string类、标准库中的string类及其接口、常用的构造函数、容量操作如size、length和capacity,以及访问和遍历string的方法。文章还提及了string的修改操作如push_back和append,并讨论了string在VS和GCC下的内存结构差异。
摘要由CSDN通过智能技术生成

📟作者主页:慢热的陕西人

🌴专栏链接:C++

📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言

本博客主要内容讲解了C++中的string类以及类内的一些常用函数

C++string类

Ⅰ. 为什么要学习string类

首先我们在C语言中有字符串的概念,是一些以\0结尾的字符的集合,而且C语言中也有很多和字符串相关的函数例如:strstr等,但是C语言中是将这些函数和字符串是分离开来的,这不符面向对象变成的思想,而且空间管理是交给用户自己来处理,非常容易出现越界问题。所以在C++中将字符串和字符串相关的函数集成在一个类里面,提高编程效率。

Ⅱ. 标准库中的string类

Ⅱ. Ⅰ. string类的了解

这里首先附上string类的文档string - C++ Reference (nonplussing)

  • 字符串是表示字符序列的类

  • 标准的字符串类提供了对此类对象的支持,其接口类似于标准字容器的接口,但添加了专门用于操作 单字节字符字符串的设计特性

  • string类是使用char(即作为它的字符类型,使用它的默认char_traitsallocator(分配器)类型(关于模板的更多信 息,请参阅basic_string)

  • string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traitsallocator(分配器)作为basic_string的默认参数(根于更多的模板信息请参考basic_string)。

  • 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-81)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作

    总结:

    • string是表示字符串的字符串类
    • 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作
    • string在底层实际是:basic_string模板类的别名,typedef basic_string string
    • 不能操作多字节或者变长字符的序列

Ⅱ. Ⅱ. string类中常用接口说明

①string类对象的常见构造:

当然库中不止以下这些可以点击下面的constuct链接详细阅读。

(construct)函数名称功能说明
string()Constructs an empty string, with a length of zero characters.
string (const string& str);Constructs a copy of str.(拷贝构造)
string (size_t n, char c);Fills the string with n consecutive copies of character c.
string (const char* s);Copies the null-terminated character sequence (C-string) pointed by s

例如:

void Teststring()
{
	string s1; // 构造空的string类对象s1
	string s2("hello bit"); // 用C格式字符串构造string类对象s2
	string s3(s2); // 拷贝构造s3
}

②string类对象的容量操作:

函数名称功能说明
sizeReturns the length of the string, in terms of bytes(我们更常用这个相比于length2
lengthReturns the length of the string, in terms of bytes
capacityReturns the size of the storage space currently allocated for the string, expressed in terms of bytes
reserveRequests that the string capacity be adapted to a planned change in size to a length of up to n characters
clearErases the contents of the string, which becomes an empty string (with a length of 0 characters).
resizeResizes the string to a length of n characters.
emptyReturns whether the string is empty (i.e. whether its length is 0).

注意:

  • clear()只是将string中有效字符清空,不改变底层空间大小。

  • resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字 符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的 元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大 小,如果是将元素个数减少,底层空间总大小不变。

  • reserve(size_t res_arg = 0):为string预留空间,不改变有效元素个数,当reserve的参数小于 string的底层空间总大小时,reserver不会改变容量大小

void Teststring1()
{
	// 注意:string类对象支持直接用cin和cout进行输入和输出
	string s("hello, bit!!!");
	cout << s.size() << endl;
	cout << s.length() << endl;
	cout << s.capacity() << endl;
	cout << s << endl;

	// 将s中的字符串清空,注意清空时只是将size清0,不改变底层空间的大小
	s.clear();
	cout << s.size() << endl;
	cout << s.capacity() << endl;

	// 将s中有效字符个数增加到10个,多出位置用'a'进行填充
	// “aaaaaaaaaa”
	s.resize(10, 'a');
	cout << s.size() << endl;
	cout << s.capacity() << endl;

	// 将s中有效字符个数增加到15个,多出位置用缺省值'\0'进行填充
	// "aaaaaaaaaa\0\0\0\0\0"
	// 注意此时s中有效字符个数已经增加到15个
	s.resize(15);
	cout << s.size() << endl;
	cout << s.capacity() << endl;
	cout << s << endl;

	// 将s中有效字符个数缩小到5个
	s.resize(5);
	cout << s.size() << endl;
	cout << s.capacity() << endl;
	cout << s << endl;
}

③string类对象的访问及遍历操作

函数名称功能说明
operator[ ]Returns a reference to the character at position pos in the string.
begin + endbegin: Returns an iterator pointing to the first character of the string. end: Returns an iterator pointing to the past-the-end character of the string.
rbegin + rendrbegin: Returns a reverse iterator pointing to the last character of the string. rend: Returns a reverse iterator pointing to the theoretical element preceding the first character of the string
范围forC++11支持更简洁的范围for的新遍历方式(底层还是迭代器(iterator))

范围for例子:

int arr[5] = {10, 20, 30, 40, 50};
for (int x : arr) {
    // 打印每一个元素
    std::cout << x << " ";
}

访问元素及遍历例子:

	string s("hello xupt");
	// 3种遍历方式:
	// 需要注意的以下三种方式除了遍历string对象,还可以遍历是修改string中的字符,
	// 另外以下三种方式对于string而言,第一种使用最多
	// 1. for+operator[]
	for (size_t i = 0; i < s.size(); ++i)
		cout << s[i] << endl;

	// 2.迭代器
	string::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << endl;
		++it;
	}

	// string::reverse_iterator rit = s.rbegin();
	// C++11之后,直接使用auto定义迭代器,让编译器推到迭代器的类型
	auto rit = s.rbegin();
	while (rit != s.rend())
		cout << *rit << endl;

	// 3.范围for
	for (auto ch : s)
		cout << ch << endl;

④string类对象的修改操作:

函数名称功能说明
push_backAppends character c to the end of the string, increasing its length by one.
appendExtends the string by appending additional characters at the end of its current value:
operator+=Extends the string by appending additional characters at the end of its current value:
c_strReturns a pointer to an array that contains a null-terminated sequence of characters (i.e., a C-string) representing the current value of the string object.
find + nposfind: Searches the string for the first occurrence of the sequence specified by its arguments. npos :Maximum value for size_t static const size_t npos = -1;
rfindSearches the string for the last occurrence of the sequence specified by its arguments.
substrReturns a newly constructed string object with its value initialized to a copy of a substring of this object.

注意:

  • 在string尾部追加字符时,s.push_back© / s.append(1, c) / s += 'c’三种的实现方式差不多,一般 情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。
  • 对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好(因为扩容是需要一定的时间代价的,提前扩容的话,就可以避免反复扩容的情况,从而达到节省时间的目的)。
	string str;
	str.push_back(' ');   // 在str后插入空格
	str.append("hello");  // 在str后追加一个字符"hello"
	str += 'b';           // 在str后追加一个字符'b'   
	str += "it";          // 在str后追加一个字符串"it"
	cout << str << endl;
	cout << str.c_str() << endl;   // 以C语言的方式打印字符串

	// 获取file的后缀
	string file("string.cpp");
	size_t pos = file.rfind('.');
	string suffix(file.substr(pos, file.size() - pos));
	cout << suffix << endl;

	// npos是string里面的一个静态成员变量
	// static const size_t npos = -1;

	// 取出url中的域名
	string url("http://www.cplusplus.com/reference/string/string/find/");
	cout << url << endl;
	size_t start = url.find("://");
	if (start == string::npos)
	{
		cout << "invalid url" << endl;
		return;
    }

⑤string类非成员函数

函数功能说明
operator+3Returns a newly constructed string object with its value being the concatenation of the characters in lhs4 followed by those of rhs.4
operator>>Extracts a string from the input stream is, storing the sequence in str, which is overwritten (the previous value of str is replaced).
operator<<Inserts the sequence of characters that conforms value of str into os.
getlineExtracts characters from is and stores them into str until the delimitation character delim is found (or the newline character, '\n', for (2)).
relational operators Performs the appropriate comparison operation between the string objects lhs and rhs.

⑥vs和g++下string结构的说明

注意:下述结构都是在32位平台下验证的。

  • vs下的string结构:

    string总共占28个字节,内部结构稍微复杂一点,先是有一个联合体,联合体用来定义string中字符串的存储空间:

    • 当字符串长度小于16时,使用内部固定的字符数组来存放
    • 当字符串长度大于等于16时,从堆上开辟空间
    union _Bxty
    { 	// storage for small buffer or pointer to larger one
     	value_type _Buf[_BUF_SIZE];
     	pointer _Ptr;
     	char _Alias[_BUF_SIZE]; // to permit aliasing
    } _Bx;
    
    

    这种设计也是有一定道理的,大多数情况下字符串的长度都小于16,那string对象创建好之后,内 部已经有了16个字符数组的固定空间,不需要通过堆创建,效率高。

    其次:还有一个size_t字段保存字符串长度,一个size_t字段保存从堆上开辟空间总的容量

    最后:还有一个指针做一些其他事情。

    故总共占16+4+4+4=28个字节。

  • g++下string的结构

    G++下,string是通过写时拷贝实现的,string对象总共占4个字节,内部只包含了一个指针,该指 针将来指向一块堆空间,内部包含了如下字段:

    • 空间总大小
    • 字符串有效长度
    • 引用计数
    struct _Rep_base
    {
     size_type _M_length;
     size_type _M_capacity;
     _Atomic_word _M_refcount;
    };
    
    • 指向堆空间的指针,用来存储字符串.

到这本篇博客的内容就到此结束了。
如果觉得本篇博客内容对你有所帮助的话,可以点赞,收藏,顺便关注一下!
如果文章内容有错误,欢迎在评论区指正

在这里插入图片描述


  1. 是一种字符编码方式详细了解可查看这个文章Unicode、UTF-8、UTF-16 终于懂了 - 知乎 ↩︎

  2. size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一 致,一般情况下基本都是用size()。 ↩︎

  3. 尽量少用,因为传值返回,会导致拷贝效率低 ↩︎

  4. 分别是运算符左侧和右侧的值 ↩︎ ↩︎

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SummerM.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值