C++奇迹之旅:string类对象的容量操作

文章目录


📝 string类的常用接口

string网址查询:https://legacy.cplusplus.com/reference/string/string/

🌉 string类对象的容量操作

函数名称 功能说明
size(重点) 返回字符串有效字符长度
length 返回字符串有效字符长度
capacity 返回空间总大小
empty (重点) 检测字符串释放为空串,是返回true,否则返回false
clear (重点) 清空有效字符
reserve (重点) 为字符串预留空间**
resize (重点) 将有效字符的个数该成n个,多出的空间用字符c填充

🌠size

  1. size---》返回字符串的长度(以字节为单位)。
cpp 复制代码
size_t size() const;
cpp 复制代码
string str("hello C++");
cout << "The size of str is " << str.size() << endl;

🌠length

  1. length---》返回字符串的长度(以字节为单位)
cpp 复制代码
size_t length() const;
cpp 复制代码
string str2("hello string");
cout << "The lenth of str2 is " << str2.length() << endl;

string::sizestring::length 是同义词,返回完全相同的值。

🌠capacity

  1. capacity---->返回当前为字符串分配的存储空间的大小,以字节表示。
cpp 复制代码
size_t capacity() const;

之所以 str.capacity() 的值是 15,是因为 C++ 标准库在创建字符串时会分配一些额外的内存空间来应对未来可能的字符串增长。这个额外的内存空间被称为 "预留空间"。

字符串 "hello C++"10 个字符,但是 C++ 标准库在创建这个字符串时会分配 15 个字符的内存空间。这样可以避免频繁的内存重新分配操作,提高性能,所以 str.capacity() 的值是 15

🌠clear

  1. clear--》擦除字符串的内容,该字符串将变为空字符串(长度为 0 个字符)。
cpp 复制代码
void clear();

clear擦除字符串的内容,该字符串将变为空字符串,长度为0,但是存储空间没有改变

cpp 复制代码
int main()
{
	string s1("hello C++");
	cout << s1 << endl;
	s1.clear();
	cout << s1 << endl;
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;

	return 0;
}

🌠empty

  1. empty--》返回字符串是否为空(即其长度是否为 0)
    此函数不会以任何方式修改字符串的值。若要清除字符串的内容,请看string::clear
cpp 复制代码
bool empty() const;

如果字符串长度为 0,则为 true,否则为 false

cpp 复制代码
int main()
{
	string str1;// 创建一个空字符串
	string str2 = "Hello, world!"; // 创建一个非空字符串

	if (str1.empty())
	{
		cout << "str1 is empty." << endl;
	}
	else
	{
		cout << "str1 is not empty." << endl;
	}

	if (str2.empty()) 
	{
		std::cout << "str2 is empty." << std::endl;
	}
	else {
		std::cout << "str2 is not empty." << std::endl;
	}
	return 0;
}

🌠reserve

  1. reserve ---》为字符串预留空间
    std::string::reserve()std::string 类的一个成员函数,用于预先分配内存空间,以提高字符串的性能。

当你需要向字符串中添加大量字符时,使用 reserve() 函数可以避免频繁的内存分配和拷贝操作,从而提高程序的性能。

cpp 复制代码
int main()
{
	string str;
	//不使用reserve
	for (int i = 0; i < 1000000; i++)
	{
		str += 'a';
	}
	cout << "size: " << str.size() << ",Capacity: " << str.capacity() << endl;
	
	//使用reserve()
	string str2;
	str2.reserve(1000000);
	for (int i = 0; i < 1000000; i++)
	{
		str2 += 'a';
	}

	cout << "size: " << str2.size() << ",Capacity: " << str2.capacity() << endl;

	return 0;
}

可以看到,在使用 reserve() 函数的情况下,str2 的容量(capacity)与大小(size)相同,而在不使用 reserve() 函数的情况下,str 的容量大于其大小。这就是 reserve() 函数的作用:它可以预先分配内存空间,避免频繁的内存分配和拷贝操作,从而提高程序的性能。

cpp 复制代码
str2.reserve(10);//容量不足会怎么样?

当你将 str2.reserve(10) 设置的容量远小于实际需要的容量,输出结果也会显示 Capacity: 1170118。这是因为 std::string 的内部实现机制。
当你使用 reserve() 函数时,它会尝试分配指定大小的内存空间。但是,如果实际需要的空间大于指定的空间,std::string 会自动增加内存空间,以满足实际需求。这个过程称为"内存重新分配"。

即使只预留了 10 个字符的空间,但当你向 str2 添加 1,000,000 个字符时,std::string 会自动增加内存空间,以容纳所有的字符。这就是为什么最终的容量会大于 1,000,000 的原因。
std::string 的容量通常会比实际需要的空间大一些,这是为了提高性能。当需要添加新的字符时,不需要频繁地重新分配内存,从而避免了内存拷贝的开销。

  • 增长策略:
    当向 std::string 添加字符时,如果当前容量不足,标准库会自动分配一个更大的内存块。增长策略通常是以当前容量的 2 倍或 1.5 倍来扩展容量,以减少内存重新分配的次数。
cpp 复制代码
//利用reserve提高插入数据的效率,避免增容带来的开销
void TestPushBack()
{
	string s;
	size_t sz = s.capacity();
	cout << "making s grow:\n";
	for (int i = 0; i < 100; ++i)
	{
		s.push_back('c');
		if (sz != s.capacity())
		{
			sz = s.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}
}
  • 构建vector时,如果提前已经知道string中大概要放多少个元素,可以提前将string中空间设置好
cpp 复制代码
void TestPushBackReserve()
{
	string s;
	s.reserve(100);
	size_t sz = s.capacity();

	cout << "making s grow:\n";
	for (int i = 0; i < 100; ++i)
	{
		s.push_back('c');
		if (sz != s.capacity())
		{
			sz = s.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}
}

🌉resize

  1. resize ---》用来改变 std::string 对象的大小
    两种语法:
cpp 复制代码
void resize (size_t n);
void resize (size_t n, char c);
  • 第一种形式的 resize() 函数会将 std::string 的大小设置为 n 个字符,并用默认值 (通常是 '\0') 填充新增的字符。
cpp 复制代码
void resize (size_t n);

例子:

cpp 复制代码
string str = "Hello, world!";
cout << "size: " << str.size() << ",Capacity: " << str.capacity() << endl;
str.resize(20);
cout << "size: " << str.size() << ",Capacity: " << str.capacity() << endl;

可以看出:与 reserve() 函数不同,resize() 函数不仅改变了 std::string 的容量,还改变了它的大小。这意味着,调用 resize() 函数后,std::stringsize()capacity() 函数返回的值都会发生变化。

  1. 将字符串大小设置为 20 个字符,并用字符 'x' 填充新增的部分
cpp 复制代码
string str = "Hello, world!";
str.resize(20, 'x');
cout << str << endl;
  1. 将字符串大小缩小到 5 个字符:
cpp 复制代码
	string str = "Hello, world!";
	str.resize(20, 'x');
	cout << str << std::endl;

注意:如果 n 小于当前 std::string 的大小,则 resize() 函数会截断字符串,删除超出部分的字符。如果 n 大于当前 std::string 的大小,则 resize() 函数会扩展字符串,并用指定的字符填充新增的部分。


🚩总结

相关推荐
轻口味25 分钟前
命名空间与模块化概述
开发语言·前端·javascript
苹果醋31 小时前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
晓纪同学1 小时前
QT-简单视觉框架代码
开发语言·qt
威桑1 小时前
Qt SizePolicy详解:minimum 与 minimumExpanding 的区别
开发语言·qt·扩张策略
Hello.Reader1 小时前
深入解析 Apache APISIX
java·apache
飞飞-躺着更舒服1 小时前
【QT】实现电子飞行显示器(简易版)
开发语言·qt
明月看潮生1 小时前
青少年编程与数学 02-004 Go语言Web编程 16课题、并发编程
开发语言·青少年编程·并发编程·编程与数学·goweb
明月看潮生2 小时前
青少年编程与数学 02-004 Go语言Web编程 17课题、静态文件
开发语言·青少年编程·编程与数学·goweb
Java Fans2 小时前
C# 中串口读取问题及解决方案
开发语言·c#
盛派网络小助手2 小时前
微信 SDK 更新 Sample,NCF 文档和模板更新,更多更新日志,欢迎解锁
开发语言·人工智能·后端·架构·c#