C++中的string类

一、string类(了解)

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

二、string了解常用接口

2.1构造函数

int main()
{
	string s1("hello world");//带参构造
	string s2;//无参构造
	string s3(5, 'x');
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;

	return 0;
}

C++中的string类_第1张图片

string(const char* str = "")
	: _str(new char[strlen(str) + 1])
	, _size(strlen(str))
	, _capacity(_size)
{
	memcpy(_str, str, _size + 1);
}

2.2拷贝构造

拷贝构造实现的是深拷贝,会再开辟一段新的空间。如果不是深拷贝,则会使同一块空间调用两次析构函数。发生错误!

int main()
{
	string s1("hello world");//带参构造
	string s2(s1);//拷贝构造
	cout << s1 << endl;
	cout << s2 << endl;

	return 0;
}

C++中的string类_第2张图片

//传统写法
string(const string& str)
{
	_str = new char[str._capacity + 1];
	memcpy(_str, str._str, str._capacity + 1);
	_size = str._size;
	_capacity = str._capacity;
}

以上拷贝构造是传统写法,尽量使用传统写法,因为现代写法会有硬伤,如果要拷贝的字符串是hello\0world,那么只会拷贝hello,遇到\0就结束。

2.3析构函数

~string()
{
    delete[] _str;
	_str = nullptr;
	_size = _capacity = 0;
}

2.4 size()

int main()
{
	string s1("hello");//带参构造
	cout << s1.size() << endl;
	return 0;
}

C++中的string类_第3张图片

size是有效是否的个数,不包括\0

2.5 reserve()

C++中的string类_第4张图片

为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserve不会改变容量大小。(只大不小)

2.6 resize()

C++中的string类_第5张图片

C++中的string类_第6张图片

C++中的string类_第7张图片

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

2.7 operator[]

int main()
{
	string s1("hello world");//带参构造
	for (int i = 0; i < s1.size(); i++)
	{
		cout << s1[i] << " ";
	}
	cout << endl;
	return 0;
}

C++中的string类_第8张图片

重载[],类似于下标的方式来索引元素。

2.8 begin() & end()

通过迭代器来遍历string,begin获取第一个字符的迭代器,end获取最后一个字符下一个位置的迭代器。

int main()
{
	string s1("hello world");//带参构造
    //string::iterator it = s1.begin();
	auto it = s1.begin();//auto自动类型识别

	while (it != s1.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
	return 0;
}

C++中的string类_第9张图片

2.9 范围for

范围for底层就是迭代器

int main()
{
	string s1("hello world");//带参构造
	for (auto ch : s1)
	{
		cout << ch << " ";
	}
	cout << endl;
	return 0;
}

C++中的string类_第10张图片

2.10 push_back()

在字符串后尾插字符

int main()
{
	string s1("hello world");//带参构造
	cout << s1 << endl;
	s1.push_back('x');
	cout << s1 << endl;
	return 0;
}

C++中的string类_第11张图片

2.11 append()

在字符串后追加一个字符串

int main()
{
	string s1("hello world");//带参构造
	cout << s1 << endl;
	s1.append("xxxxxxxxxxxxxxxxxx");
	cout << s1 << endl;
	return 0;
}

C++中的string类_第12张图片

2.12 operator+=

即可以+=字符,又可以+=字符串,底层实现了string& operator+=(cosnt char ch)和string& operator+=(cosnt char* str)的重载。

int main()
{
	string s1("hello world");//带参构造
	cout << s1 << endl;
	s1 += 'x';
	cout << s1 << endl;
	s1 += "yyyyyyyyyyyyyyy";
	cout << s1 << endl;

	return 0;
}

C++中的string类_第13张图片

2.13 c_str()

返回的是char* 的字符串,为了兼容C语言。底层实现const char* c_str() const;

int main()
{
	string s1("hello world");//带参构造
	cout << s1.c_str() << endl;
	cout << s1 << endl;
	return 0;
}

C++中的string类_第14张图片

2.14 find()

C++中的string类_第15张图片

int main()
{
	string s1("hello world");//带参构造
	cout << s1.find('w') << endl;
	cout << s1.find('l', 5) << endl;
	cout << s1.find("wor") << endl;
	return 0;
}

C++中的string类_第16张图片

2.15 substr()

C++中的string类_第17张图片

int main()
{
	string s1("hello world");//带参构造
	cout << s1.substr(5, 3) << endl;
	return 0;
}

C++中的string类_第18张图片

2.16 operator>>

//流提取
istream& operator>>(istream& in, string& str)
{
	str.clear();
	
	char ch = in.get();
	//读取出前面的空格或换行字符
	while (ch == ' ' || ch == '\n')
	{
		ch = in.get();
	}
	while (ch != '\n')
	{
		str += ch;
		ch = in.get();
	}
	
	return in;
}

2.17 operator<<

输出到屏幕上,string输出是按size的大小输出,不是遇到\0结束。

//流插入
ostream& operator<<(ostream& out, const string& str)
{
	for (auto ch : str)
	{
		out << ch;
	}
	return out;
}

三、理解浅拷贝和深拷贝

3.1浅拷贝

C++中的string类_第19张图片说明:上述String类没有显式定义其拷贝构造函数与赋值运算符重载,此时编译器会合成默认的,当用s1构造s2时,编译器会调用默认的拷贝构造。最终导致的问题是,s1、s2共用同一块内存空间,在释放时同一块空间被释放多次而引起程序崩溃,这种拷贝方式,称为浅拷贝。

3.2深拷贝

C++中的string类_第20张图片
如果一个类中涉及到资源的管理,其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出。一般情况都是按照深拷贝方式提供。

四、传统写法和现代写法

//传统写法——赋值元素符重载
String& operator=(const String& s)
{
    if (this != &s)
    {
        char* pStr = new char[strlen(s._str) + 1];
        strcpy(pStr, s._str);
        delete[] _str;
        _str = pStr;
    }
    return *this;
}
//现代写法——赋值元素符重载
string& operator=(string tmp)
{
	swap(tmp);
	return *this;
}

调用拷贝构造创建tmp,将tmp和*this交换,出作用域调用tmp的析构函数。

你可能感兴趣的:(c++,c++)