最近写的一个程序,为了使接口简便,在返回字符串的时候不得已使用了stl::string,但是又担心如果此方法被频繁调用,可能会导致性能问题,于是尝试用一些底层机制去优化stl::string。
stl::string是怎么实现的呢?脑海中有一个猜想,首先就是这样:
class string
{
private:
char* m_str;
int m_len;
};
为了验证这个想法,于是用sizeof(string)将类型的长度打出来看看…………结果让人大跌眼镜,还要我不戴眼睛!在GCC中,sizeof(string)=4。怎么可能嘛?如果就四个字节,哪里放长度信息呢?
再次输出更多信息来验证:
string str = "abcde";
printf("addr=%08x, this=%08x, str=[%s]\n", (unsigned int)str.c_str(), *((unsigned int*)&str), str.c_str());
string自身的四个字节存储的内容竟然就是所指向的字符串的指针!!!
难道?难道,string在GCC中的实现,就仅仅只是char*,如果调用str.length(),就是悄悄去调用strlen()?
再写一个输入内存的16进制字符串的函数PrintHex(),用这个函数将内存中的信息打印出来,实现如下:
void PrintHex(char* Buffer, int Size, FILE* fp =stdout)
...{
fprintf(fp, "===================================================== ");
char* p = NULL;
int i;
for (i=0, p = Buffer; i<Size; i++, p++)
...{
fprintf(fp, "%02x ", (unsigned char)*p);
if (i%16==15)
...{
fprintf(fp, " ");
}
}
fprintf(fp, " ===================================================== ");
}
打印一下内存的信息试试:
string str="abcde";
PrintHex(((char*)str.c_str())-20, 40);
分析16进制字符串,大概明白点string的内部了,看懂的部分大约是这样的:
struct string_buffer
{
int Length;
int Capacity;
int unknown;
char Content[_Capacity]; // _Capacity = Capacity
};
而string只是指向这样一个内存块的content部分的指针。分配多个string,就会发现这些内存块隔得很近。
以上分析说明:
1、string只是指向字符串池中内容部分的一个指针;(将string作为参数或者返回值,性能都很高,等同于const string&这样的参数)
2、字符串池的块中缓存了长度和预留空间等信息,所以,不要使用C的字符串函数来操作string的任何内容,结果可能不一致。
最后,试试在VC中打印:sizeof(string),天哪!28个字节!微软的STL实现,不敢恭维啊!
分享到:
相关推荐
在C语言中,原生类型并不包含字符串,但它是编程中不可或缺的一部分。为了弥补这一不足,我们可以创建一个名为"StringLib"的C库,来为C语言添加对字符串的便捷处理。这个库的核心目标是定义一个新的数据类型,代表...
3. **字符串处理**:`strcpy()`、`strcat()`、`strcmp()`、`strlen()`等函数处理字符串的复制、连接、比较和长度获取。`strstr()`和`strchr()`则用于查找子串和字符在字符串中的位置。 4. **数学运算**:`sqrt()`, ...
- **应用场景**: 当需要从程序代码中读取字符串或其他常量数据时。 - **EEPROM数据存储器操作**: - **读写操作**: 使用AVR单片机提供的EEPROM库函数进行数据的存储和读取。 - **注意事项**: EEPROM写入次数有限...
CJSON库的核心函数包括`cJSON_Parse()`用于解析JSON字符串,以及`cJSON_Print()`和`cJSON_PrintUnformatted()`用于生成JSON字符串。 要将CJSON库集成到STM32项目中,首先需要下载CJSON的源代码,并将其编译为适用于...
格式字符串语法类似于 Python 中 str.format 使用的语法。 该库是完全类型安全的,自动内存管理可防止缓冲区溢出,使用异常或在编译时报告格式字符串中的错误。 该库生成紧凑的每次调用编译代码。 该库是高度可移植...
2. `jsmn_parse`: 核心解析函数,接受JSON字符串和令牌池,返回解析结果。 3. `jsmn_get_val`: 根据令牌获取JSON值,可能是字符串、数字或其他类型。 4. `jsmn_parent_token`: 获取给定令牌的父令牌,用于构建JSON...
2. **字符串处理**:strcpy、strcat、strcmp等函数的源码,揭示字符串操作的底层逻辑。 3. **I/O操作**:包括文件读写、标准输入输出流的管理,如fopen、fclose、printf等函数的实现。 4. **进程与线程**:fork、...
- 字符串处理:优化字符串拷贝和比较操作,可能使用了字符串池技术。 在实际应用中,我们通常会结合具体需求来选择合适的JSON库。例如,如果项目中涉及到大量JSON数据的读写,那么性能就成为首要考虑因素;而如果...
蓄水池算法 leetcode LeetCode 一、编译器 (1)Visual Studio Code 简单的代码都用 VSCode 来实现。...复杂的代码(查找内存溢出)使用 ...字符串的反转 344、541、557、151 字符的统计 387、389、383、242、49
glibc作为C语言的标准库,提供了各种优化的函数实现,如内存管理、数学运算、字符串操作等。通过选择合适的glibc版本和配置,以及使用库提供的特定优化功能,如内存池(Memory Pools)和异步信号安全(Asynchronous...
Nginx对C语言的字符串类型进行了封装,增加了字符串长度的信息,以便更高效地操作。在`core/ngx_string.h`中定义了几个关键的字符串类型: - `ngx_str_t`:包含字符串长度和指向字符串的指针。 - `ngx_keyval_t`:...
Redis是用C语言编写的,支持多种键值数据类型,包括字符串、散列、列表、集合和有序集合,这些类型适应了各种不同的存储需求。例如,字符串是最基础的数据类型,散列则适合存储对象,列表可用于消息队列,集合用于不...
指针和字符串是C语言中的高级概念,它们是实现动态内存管理和字符串操作的基础。Objective-C中的类和实例创建机制,方法调用,封装,继承等面向对象的概念都在第3章中有详细描述,这为理解Objective-C特有的面向对象...
1. **Redis通信协议**: hiredis设计时遵循了Redis的简单字符串协议,使得客户端与服务端的交互更为高效。它理解并解析Redis命令的回复格式,包括简单字符串、错误、整数、数组和多字节字符串。 2. **非阻塞I/O**: ...
这个库包含了许多关键组件,如容器、算法、迭代器、智能指针、字符串、I/O流、异常处理等,这些都是C++程序员日常开发中必不可少的工具。 标题中的"libstdc++库.zip"显然是一个包含了不同版本的libstdc++库的压缩...
- **字符串类型**(String):最基础的数据类型,可以用来存储字符串或数字。 - **哈希类型**(Hash):用于存储字段和值的映射关系,适合用来存储对象。 - **列表类型**(List):按照插入顺序排序的元素集合,适用...
HTMLCSS的存储效率也很高,它利用共享的字符串池和智能CSS缓存来最小化内存中HTML文档的大小。 我将HTMLCSS作为Apache许可版本2.0下的开源提供,但与GPL2 / LGPL2应用程序一起使用时例外,它使您几乎可以做任何想做...
它不仅提供了高速的数据读写能力,还支持多种数据结构,如字符串(Strings)、列表(Lists)、集合(Sets)、有序集合(ZSets)以及哈希(Hashes)等。以下是Redis的一些关键特点: 1. **高性能**: Redis的读取速度可以达到每...