【C++】string类接口的了解和使用(一)

简介: 【C++】string类接口的了解和使用

为什么我们要学string类呢?那是必须是为了方便啊!在C语言中,我们创建一个字符串,有很多操作或者必须要注意的细节会把控不住,所以C++中出现了string类,让我们应对字符串等oj题也方便快捷了许多!

一、STL的介绍

STL(standard template libaray- 标准模板库 ) : 是 C++ 标准库的重要组成部分 ,不仅是一个可复用的组件库,而且 是一个包罗数据结构与算法的软件框架 。

STL 的六大组件 :仿函数、算法、迭代器、空间配置器、容器、配接器。

这些在我们接下来的学习都会深入学习!

网上有句话说: “ 不懂 STL ,不要说你会 C++” 。 STL 是 C++ 中的优秀作品,有了它的陪伴,许多底层的数据结构

以及算法都不需要自己重新造轮子,站在前人的肩膀上,健步如飞的快速开发。

二、标准库中的string类

1、简介string

string是一个模板,是因为编码不同,导致char的字节数不同,所以需要模板来适应不同的编码类型,原型差不多就是这样的:

我们接下来研究的:utf-8,char为一个字节的string类

2、库中的string类的常用接口说明

  1.构造函数

在学习任何类之前,当然要先看它的构造函数了!(我们只了解重要且常用的)

构造函数:直接上例子:

 可以看得出,s1为默认的构造函数


s2是带参的构造函数(理解:会开辟一段空间,将内容存起来)


s3的构造方式,会发生隐式类型转换,会产生临时变量,先构造,再拷贝构造,优化后就是构造


s4构造是用n个char c 字符去初始化


拷贝构造:自定义类型拷贝会发生深拷贝,所以形参一般要用引用减少拷贝,提高效率


s5,s6都是拷贝构造


2.npos

npos是一个静态成员变量,无符号整型,是一个极大的数。

对于这个构造函数,是在str的pos位置开始向后len的长度,这段字符串进行初始化。

那默认不传len,len的值就是npos,是一个非常大的数,当len大于str的长度时,默认到了str的最后一位。

3.遍历

共有三种遍历方式:

void test2()
{
  string s1("12345678");
  // 1、下标 []
  for (size_t i = 0; i < s1.size(); ++i)
  {
    s1[i]++;
  }
  cout << s1 << endl;
  // 2、范围for
  for (auto& ch : s1)
  {
    ch--;
  }
  cout << s1 << endl;
  // 3、迭代器  -- 通用的访问形式
  string::iterator it1 = s1.begin();
  while (it1 != s1.end())
  {
    *it1 += 1;
    ++it1;    // 把string里的内容每一个都加了一
  }
  it1 = s1.begin();
  while (it1 != s1.end())
  {
    cout << *it1 << " ";   //打印每一个内容
    ++it1;
  }
  cout << endl;
}

可以看的出:operator[]有两个接口,一个是有const,一个没有const


operator[],是一个可读且可写的接口。


当const只读对象调用时,就会调用const接口


当只写对象调用时,就会调用非const,


所以对于即可写又可读的接口函数来说,就有两个版本,const和非const


还有一点:operator[]内部有防止越界访问的功能:assert(pos<=size);


迭代器的遍历方法:


这里的迭代器是string类的自定义的一种类型,需要string::


迭代器我们现在可以看作是 和指针相差不多的东西(行为像指针),但他又不是指针,具体的底层我们后面会见面。


begin()就是指向第一个位置,end()指向最后一个有效字符的下一个位置


迭代器要注意的地方:

我们可以看到:迭代器也分为const和非const,那什么时候分别用哪个呢?

const_iterator:只能在const对象下使用,并且const迭代器可以改变迭代器本身,但不能改变迭代器所指向的内容

迭代器有正向迭代器和反向迭代器:

void Print(const string& s)
{
  // 只读不写,可以遍历改变it,但不能改变他指向内容
  string::const_iterator it = s.begin(); //正向迭代器
  while (it != s.end())
  {
    // *it += 1;  错误!
    cout << *it << " ";
    ++it;
      //正向迭代器就是正着迭代++
  }
  }
  cout << endl;
  //string::const_reverse_iterator rit = s.rbegin();
  auto rit = s.rbegin();       //反向迭代器
  while (rit != s.rend())
  {
    cout << *rit << " ";
    ++rit;
       //都是++,这里不可以类比指针反向迭代器就是反着迭代++
  }
  cout << endl;
}

学会了吗?

3.capacity

1.size,lenth,max_size,capacity

在string中,我们会怎么描述字符串长度??length是不是更贴合,那为什么又有size呢??


因为string是早于stl的,在它之后size更普遍适用,为了普遍化,那只能添加一个size了


size==length,就是求长度或者字符个数。(length淘汰!!)只读接口,加const

capacity:string的容量,和size可不相同。

clear:因为stl只是规范了每个接口名字或者参数,但并没有将每一个容器函数的细节拿捏死,所以对于clear,我们并不知道他清空数据以后,是否还要回收空间。得需要验证!

void test4()
{
  string s("hello world");
  cout << s.size() << endl;
  cout << s.length() << endl;
  cout << s.capacity() << endl;
  s.clear();
  cout << s << endl;
  cout << s.capacity() << endl;
}

可以发现,clear之后并没有回收空间,也不会缩容

empty(),就是来判空的

2.shrink_to_fit

当capacity大于size时,将size和capacity保持一致,会缩容,但缩容代价还是挺大的,一般也不这么搞。

3.reserve、resize(重点)

只改变capacity

在我们知道需要多少空间时,插入数据,为了防止反复扩容(扩容代价大),我们可以提前预留空间,开辟好。


那到底是怎么扩的呢??一次扩多少?


我们在vs和g++上分别测试得出:vs上面会1.5倍扩容,但是存在内存对齐问题,会有些许偏差,但空间还是大于我们要开辟的。g++就是2倍扩容,要多少扩多少,不会有偏差。

第一次预留500,第一次扩容到766,第二次扩容1149,差不多就是1.5倍

resize:它改变的是 size

当n不同,resize会分为三种情况:(n为size改变后的值)


目录
相关文章
|
26天前
|
C语言 C++ 容器
【c++丨STL】string模拟实现(附源码)
本文详细介绍了如何模拟实现C++ STL中的`string`类,包括其构造函数、拷贝构造、赋值重载、析构函数等基本功能,以及字符串的插入、删除、查找、比较等操作。文章还展示了如何实现输入输出流操作符,使自定义的`string`类能够方便地与`cin`和`cout`配合使用。通过这些实现,读者不仅能加深对`string`类的理解,还能提升对C++编程技巧的掌握。
55 5
|
26天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
42 2
|
1月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
84 5
|
1月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
81 4
|
1月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
89 4
|
2月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
31 4
|
2月前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
32 4
|
2月前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
26 1
|
2月前
|
存储 编译器 C++
【C++类和对象(下)】——我与C++的不解之缘(五)
【C++类和对象(下)】——我与C++的不解之缘(五)
|
2月前
|
编译器 C++
【C++类和对象(中)】—— 我与C++的不解之缘(四)
【C++类和对象(中)】—— 我与C++的不解之缘(四)