c++ - std::string 各种长度的内存分配

标签 c++ memory-management

#include <iostream>

#include <string>

static uint32_t s_AllocCount = 0;

// Overload of new operator.
void* operator new(size_t size) {

    s_AllocCount++;
    std::cout << "Allocating " << size << " bytes\n";

    return malloc(size);
}

void PrintName(const std::string& name) {

    std::cout << name << " - " << name.length() << " characters." << std::endl;
}

int main() {

    std::string name = "123456789012345";
    PrintName(name);

    std::cout << s_AllocCount << " allocations" << std::endl;
    std::cin.get();
}

上面的代码是 How to make your STRINGS FASTER in C++! 中的一个稍微修改过的版本。

我对这个程序在 x86 调试中编译的 Visual Studio 2019 中的各种输出感到困惑。

std::string name = "123456789012345";结果如下:

enter image description here

我知道为指针地址分配了 8 个字节。我明白的是这个字符串中有 15 个字节。指针地址不是指向一个 8 字节的内存块,即可以容纳 8 个字符的内存块吗?

std::string name = "1234567890123456";时,即加长1个字符为16,结果为:

enter image description here

现在,额外分配了 32 字节的内存,显然足以容纳 16 个字符。

我的理解是否正确:

  1. 第一种情况下,只有 8 个字节的堆内存被分配用于存储字符串的指针地址,并且字符串的 15 个字符被存储在堆栈上?

  2. 第二种情况下,正在分配40字节的堆内存,并且两者字符串的指针地址和字符串字符都存储在堆上?

这个问题是由引用视频的作者关于在 OpenGL 中使用 std::string 提出的。具体来说,他建议在 OpenGL 中随意使用 std::string 可以大大减慢动态场景变化。现在,我正试图更好地了解分配了多少内存以及在何处分配,这样至少我知道什么时候它可能会减慢程序速度。

因为我稍微修改了这个程序,也许代码没有按照我的想法去做,也就是说,我犯了一个编程错误。如果是这样,我将不胜感激所发现的错误。

最佳答案

我不知道分配这 8 个字节的目的是什么,但假设是典型的 std::string 实现,则不需要任何动态分配。字符串实现实现“小字符串优化”:

想法是将字符串对象视为标记 union ,将指向动态字符串的指针集作为一个成员,将大小相等的字符数组作为另一个成员。只要字符串适合 sizeof(std::string),它就存储在该数组成员中;否则动态分配字符串,并存储指针。


  1. That in the first case only 8 bytes of heap memory are being allocated for storing the string's pointer address and that the 15 characters of the string are stored on the stack?

这 8 个字节可能与字符串没有直接关系。我没有看到动态存储“字符串的指针地址”的理由。指针的地址存储在哪里,会实现什么?相反,分配可能与某些调试功能有关。

将 15 个字符存储在堆栈中可能是准确的。

关于c++ - std::string 各种长度的内存分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59035537/

相关文章:

C++ 从 Node 模拟 int main(int argc, char *argv[])

c++ - Winapi 同步进程

javascript - 原始数据方法

iphone - -[ClassRoster Controller WillChangeContent :]: message sent to deallocated instance

c - free()之前是否需要检查指针是否为空

c++ - 在扩展期间将 vector 成员插入 vector : vector. push_back(vector[0])

c++ - Bazel:相对本地路径作为 http_archive() 中的 url

c++ - 如何从 Objective-C 将数组发送到 C++ 函数

c - malloc行为解释

ios - 在 swift 中使用 objc_setAssociatedObject 时提前调用 dealloc/deinit