c++中map和string的内存分配方式

how memory allocation happens for map and string in c++

本文关键字:内存 分配 方式 string map c++      更新时间:2023-10-16

我使用map<string,string>类型的全局声明。

  1. 如果我执行代码,字符串是在动态内存中创建的吗?
  2. 映射是在动态内存还是静态内存上创建的?

#include <iostream>
#include <map>
#include <string> 
std::map<std::string, std::string> mymap;
class myObject
{
public:
    myObject()
    {
        mymap["A"] = "AString";
        mymap["B"] = "BString";
        mymap["C"] = "CString";
    }
};
int main()
{
    myObject obj1;
    std::cout << mymap["B"] << std::endl;
    return 1;
}

有一个固定大小的对象表示映射本身,您将其设置为全局(与静态存储类型相同)。它将具有某种形式的指针,指向包含映射的可变大小内容的动态内存。这包括动态内存中的字符串,但也包括动态内存中的其他内容(取决于实现)。

这个问题的正确、完整的答案可能比人们想象的要复杂得多。我给你一些提示:

  • c++标准将内存管理的细节留给实现。你真的不应该太在意这个。把精力集中在应用程序逻辑的语义上,把内存管理留给编译器。

  • 与原始数组(或std::array)不同,std::mapstd::string(实际上是std::basic_string)是容器,其大小可以在执行过程中更改,因此类通常(但不总是,见下文)不能包含所有元素本身。它们将包含一个指向动态分配内存的指针,其中保存了实际的内容。std::mapstd::string对象本身的大小(字面上是sizeof)与它们当前的内容无关。

  • 动态分配时,std::mapstd::string默认使用 std::allocator std::allocator使用placement new来分配内存(new[]不使用)。

  • 理论上,您可以使用自定义分配器而不是默认分配器,以完全不同的方式执行任何内存分配,尽管很少这样做。

  • std::string可以使用小字符串优化(SSO)实现,在这种情况下,对于小字符串将根本没有动态分配。Visual c++使用了这种技术。

  • Copy-on-Write (COW)是另一种传统的实现字符串的方法,基于相同的字符串可以共享相同的动态分配的内容的想法。在这种情况下,多个std::string对象中的指针将指向相同的地址。然而,这种技术在多线程场景中一直存在问题,并且在c++ 11中实际上是不允许的;我只是为了完整起见才提到它。

  • 从c++ 11开始,std::string的内容被正式要求是连续的,即一个接一个地存储在内存中,这样你就可以取第一个元素的地址,并将内容视为一个数组。

实际上这个map<string,string>需要移动到共享内存,所以想知道内存是如何分配的,如果我想移动带有字符串的map,我需要遵循不同形式的内存管理。

如果有人知道如何做到这一点,请告诉我。