`
ah_fu
  • 浏览: 227906 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

复杂的GCC字符串池

阅读更多
    最近写的一个程序,为了使接口简便,在返回字符串的时候不得已使用了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实现,不敢恭维啊!


 
分享到:
评论

相关推荐

    StringLib C:库向C添加字符串类型

    在C语言中,原生类型并不包含字符串,但它是编程中不可或缺的一部分。为了弥补这一不足,我们可以创建一个名为"StringLib"的C库,来为C语言添加对字符串的便捷处理。这个库的核心目标是定义一个新的数据类型,代表...

    libc-html_node.tar.gz_GCC 函数_libc

    3. **字符串处理**:`strcpy()`、`strcat()`、`strcmp()`、`strlen()`等函数处理字符串的复制、连接、比较和长度获取。`strstr()`和`strchr()`则用于查找子串和字符在字符串中的位置。 4. **数学运算**:`sqrt()`, ...

    avr的gcc编程(初学者必看)

    - **应用场景**: 当需要从程序代码中读取字符串或其他常量数据时。 - **EEPROM数据存储器操作**: - **读写操作**: 使用AVR单片机提供的EEPROM库函数进行数据的存储和读取。 - **注意事项**: EEPROM写入次数有限...

    stm32解析Cjson.zip

    CJSON库的核心函数包括`cJSON_Parse()`用于解析JSON字符串,以及`cJSON_Print()`和`cJSON_PrintUnformatted()`用于生成JSON字符串。 要将CJSON库集成到STM32项目中,首先需要下载CJSON的源代码,并将其编译为适用于...

    fmt:格式化库作为 C stdio 和 C++ iostreams 的替代方案-开源

    格式字符串语法类似于 Python 中 str.format 使用的语法。 该库是完全类型安全的,自动内存管理可防止缓冲区溢出,使用异常或在编译时报告格式字符串中的错误。 该库生成紧凑的每次调用编译代码。 该库是高度可移植...

    C语言JSON格式数据解析库及测试代码

    2. `jsmn_parse`: 核心解析函数,接受JSON字符串和令牌池,返回解析结果。 3. `jsmn_get_val`: 根据令牌获取JSON值,可能是字符串、数字或其他类型。 4. `jsmn_parent_token`: 获取给定令牌的父令牌,用于构建JSON...

    eglibc-2.19_libc标准库源码_639.gcc_

    2. **字符串处理**:strcpy、strcat、strcmp等函数的源码,揭示字符串操作的底层逻辑。 3. **I/O操作**:包括文件读写、标准输入输出流的管理,如fopen、fclose、printf等函数的实现。 4. **进程与线程**:fork、...

    The fastest JSON library in C.zip

    - 字符串处理:优化字符串拷贝和比较操作,可能使用了字符串池技术。 在实际应用中,我们通常会结合具体需求来选择合适的JSON库。例如,如果项目中涉及到大量JSON数据的读写,那么性能就成为首要考虑因素;而如果...

    蓄水池算法leetcode-LeetCode:LeetCode刷题

    蓄水池算法 leetcode LeetCode 一、编译器 (1)Visual Studio Code 简单的代码都用 VSCode 来实现。...复杂的代码(查找内存溢出)使用 ...字符串的反转 344、541、557、151 字符的统计 387、389、383、242、49

    使用gcc和glibc来优化程序 转载 (2).pdf

    glibc作为C语言的标准库,提供了各种优化的函数实现,如内存管理、数学运算、字符串操作等。通过选择合适的glibc版本和配置,以及使用库提供的特定优化功能,如内存池(Memory Pools)和异步信号安全(Asynchronous...

    Nginx源代码分析

    Nginx对C语言的字符串类型进行了封装,增加了字符串长度的信息,以便更高效地操作。在`core/ngx_string.h`中定义了几个关键的字符串类型: - `ngx_str_t`:包含字符串长度和指向字符串的指针。 - `ngx_keyval_t`:...

    Redis集群搭建1

    Redis是用C语言编写的,支持多种键值数据类型,包括字符串、散列、列表、集合和有序集合,这些类型适应了各种不同的存储需求。例如,字符串是最基础的数据类型,散列则适合存储对象,列表可用于消息队列,集合用于不...

    Objective-C_2.0_Mac和iOS开发实践指南

    指针和字符串是C语言中的高级概念,它们是实现动态内存管理和字符串操作的基础。Objective-C中的类和实例创建机制,方法调用,封装,继承等面向对象的概念都在第3章中有详细描述,这为理解Objective-C特有的面向对象...

    hiredis-master.zip

    1. **Redis通信协议**: hiredis设计时遵循了Redis的简单字符串协议,使得客户端与服务端的交互更为高效。它理解并解析Redis命令的回复格式,包括简单字符串、错误、整数、数组和多字节字符串。 2. **非阻塞I/O**: ...

    libstdc++库.zip

    这个库包含了许多关键组件,如容器、算法、迭代器、智能指针、字符串、I/O流、异常处理等,这些都是C++程序员日常开发中必不可少的工具。 标题中的"libstdc++库.zip"显然是一个包含了不同版本的libstdc++库的压缩...

    redis资料利于广大群众使用!!!

    - **字符串类型**(String):最基础的数据类型,可以用来存储字符串或数字。 - **哈希类型**(Hash):用于存储字段和值的映射关系,适合用来存储对象。 - **列表类型**(List):按照插入顺序排序的元素集合,适用...

    htmlcss:C语言中的轻量级HTML和CSS解析器

    HTMLCSS的存储效率也很高,它利用共享的字符串池和智能CSS缓存来最小化内存中HTML文档的大小。 我将HTMLCSS作为Apache许可版本2.0下的开源提供,但与GPL2 / LGPL2应用程序一起使用时例外,它使您几乎可以做任何想做...

    史上最全redis学习笔计

    它不仅提供了高速的数据读写能力,还支持多种数据结构,如字符串(Strings)、列表(Lists)、集合(Sets)、有序集合(ZSets)以及哈希(Hashes)等。以下是Redis的一些关键特点: 1. **高性能**: Redis的读取速度可以达到每...

Global site tag (gtag.js) - Google Analytics