C++中string类总结一:基础了解(三个默认成员函数:构造、析构、赋值,并介绍string中迭代器的使用)

一、string类相关博文


二、构造

  • string为了符合C语言的字符串规范,它不仅存字符串,还在末尾存了\0,即使是空字符串,它也有存\0
    • size()只记录string的有效字符数,不记录\0
  • string::npos:存的是size_t npos = -1
    • -1以补码的方式存储,就是11…1(32个1),给了有符号int -1给了无符号size_t,就成为了整型最大值2^32-1=4294967295(42亿9千万)
  • string构造函数部分给出的接口如下string构造具体接口
  • string构造示例:
string s1;//①无参构造(🔺)

string s2(s1);//②拷贝构造(🔺)

string s3("hello world!!!");//③ 
string s4(s3, 6, 15);//拷贝s3,从其下标为6处(w)开始==>world!!!
string s4(s3, 6);// 若第三个参数len大于后面字符长度或没传参,就拷贝到结尾

string s5 ("hello world!!!");//④带参构造(🔺)
string s5 = "hello world!!!";//也能用赋值(用到了隐式类型转换)

string s6("hello",3);//⑤s6="hel"(很少用到,不如直接少些几个字符)

string s7(100, 'x');//⑥用100个x初始化



三、析构

  • 参考文档内容:string::~string - C++ Reference (cplusplus.com)
  • 出了作用域会自动调用析构,我们不用怎么管,但是要懂得析构在被实现:
    • 析构要把指向的空间给释放掉,指向的空间和顺序表一样在堆上
    • 为什么在堆上?
      • ==> 因为我们需要往string中插入字符,若空间不足则需要扩容,而只有堆上的空间才能很好地满足我们的扩容需求

四、赋值

  • 参考文档内容:string::operator= - C++ Reference (cplusplus.com)
  • string赋值提供的接口如下:
    • 三种赋值(由于写的早,规范性不足,后两种没必要也用的很少),这三个都构成函数重载
    • 在这里插入图片描述
  • 赋值示例如下:
string s1;
string s2 = "hello world!!!"; // 构造+拷贝构造 ->优化 -> 直接构造

//赋值①:直接赋值(正常任何一个类都要支持,不写也是有默认的赋值重载)
s1 = s2;
//赋值②:字符串赋值
s1 = "xxxx"; //s1是已经存在对象,调的是赋值,不是构造
//赋值③:字符赋值
s1 = 'y';

五、迭代器

  • iterator即迭代器的意思。

    • iterator像指针一样的类型,有可能就是指针,也有可能不是指针,但它用法像指针一样
  • 任何一个数据结构的迭代器都是在其内部里的,所以迭代器属于其类域

    • 访问string的迭代器:string::iterator
    • 访问vector的迭代器:vector<int>::iterator(vector中显示实例化,内部存储数据类型为int)
    • 访问list的迭代器:list<int>::iterator
  • 迭代器的重要性:iterator是所有容器通用访问方式,且用法类似

    • string、vector等(这类底层物理空间是连续数组的)不喜欢用迭代器,因为[]更好用,可读可写;但list/map/set…只能用迭代器访问
  • 四种迭代器类型

    • 正向迭代器:iterator/ const_iterator
    • 反向迭代器:reverse_iterator / const_reverse_iterator

1、正向迭代器

  • 总体是一个左闭右开的区间:[begin,end)
  • string的正向迭代器示例
void test_string1()
{
	string s("hello");
	string::iterator it = s.begin();
	while (it != s.end())//分析点①
	{
		(*it)++;
		cout << *it << " ";
		++it;
	}
	cout << endl;
	
	/*for (auto ch : s)//分析点②
	{
		ch++;
		cout << ch << " ";
	}*/
	for (auto& ch : s)//分析点③
	{
		ch++;
		cout << ch << " ";
	}
	cout << endl;
	cout << s << endl;

//遍历list
	list<int> lt(10, 1);
	list<int>::iterator lit = lt.begin();
	while (lit != lt.end())
	{
		cout << *lit << " ";
		++lit;
	}
	cout << endl;

	for (auto e : lt)//分析点④
	{
		cout << e << " ";
	}
	cout << endl;
}
  • 分析点①==> iterator为什么采用!=来判断,而非<的原因:

    • stringvector此处可用it<s.end(),因为它们是连续的物理空间,但list就不行,不支持使用<
    • 故,it != s.end()是一种通用的写法
  • 分析点②~④ ==> 范围for

    • 范围for可以自动迭代,自动判断结束==>依次取s中每个字符,赋值给ch
    • 所有的容器,都可以采用范围for来遍历
      • 范围for事实上并没有什么含金量,其底层就是迭代器(即,分析点②底层最终会转化成分析点①类似写法了)
    • 若要修改,则需要采用引用&==>即分析点③

2、反向迭代器 rbeginrend

  • 总体是一个右闭左开的区间:[begin,end)
  • ![[Pasted image 20221113145007.png]]
void test_string3()
{
	string s("hello");
	string::reverse_iterator rit = s.rbegin();
	while (rit != s.rend())
	{
		cout << *rit << " ";
		++rit;
	}
	cout << endl;

	PrintString(s);
}

3、const迭代器

  • 一般不会将迭代器const。通常只会发生在传参的过程中,会需要const迭代器
  • const迭代器特点:可读不可写
  • const迭代器之后还提供了专门的cbegin和cend(但原来的不便删除,故也保留)
//void PrintString(string str)//①拷贝一般不好故会采用引用,但不改变,则又加上const;②或者传入的参数就是const
void PrintString(const string& str)
{
//正向的const迭代器:
	//string::const_iterator it = str.begin();//前期建议写这个,认全熟悉以下
	auto it = str.begin();//熟悉后就能用auto写了:auto不用写类型,begin返回什么用什么
	while (it != str.end())
	{
		//*it = 'x';
		cout << *it << " ";
		++it;
	}
	cout << endl;

//反向的const迭代器:
	//auto rit = str.begin();
	string::const_reverse_iterator rit = str.rbegin();
	while (rit != str.rend())
	{
		cout << *rit << " ";
		++rit;
	}
	cout << endl;
}

祝大家学习愉快 : )

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值