C++ 创建映射时如何管理内存<;字符串,向量<;字符串>&燃气轮机;通过读取文件

C++ 创建映射时如何管理内存<;字符串,向量<;字符串>&燃气轮机;通过读取文件,c++,vector,memory-management,stdmap,C++,Vector,Memory Management,Stdmap,我想知道当不同的文件存储在字符串向量的映射中时,内存是如何管理的。 我曾尝试读取不同的文件,每个文件的内存为10个月,当我使用KSySGuard检查内存时,显示的内存是我的文件内存的两倍多(~70mo)。 我为您提供了一个代码示例: 有一个函数readfile(): std::vector read_文件(std::string和path){ ifstream fichier(路径); std::向量fich; 如果(菲希尔){ 弦线; while(getline(fichier,ligne))

我想知道当不同的文件存储在字符串向量的映射中时,内存是如何管理的。 我曾尝试读取不同的文件,每个文件的内存为10个月,当我使用KSySGuard检查内存时,显示的内存是我的文件内存的两倍多(~70mo)。 我为您提供了一个代码示例: 有一个函数readfile():

std::vector read_文件(std::string和path){
ifstream fichier(路径);
std::向量fich;
如果(菲希尔){
弦线;
while(getline(fichier,ligne)){
fich.向后推(直线);
}
}
fichier.close();
回程费;
}
此功能用于另一个正在构建我的地图的程序:

std::map<std::string, std::vector<std::string>> buildmap(std::string folder){
    std::map<std::string,std::vector<std::string>> evaluations; std::vector<std::string> vecFiles = {"file1","file2","file3"};
    for( auto i = 0; i < vecFiles.size(); i++ )
    {
        std::stringstream strad;
        strad <<vecFiles[i] ;
        std::string path(folder+vecFiles[i]);
        std::vector<std::string> a = read_file(path);
        evaluations[strad.str()]=a;
    }
    return evaluations;   
}
std::map buildmap(std::string文件夹){
std::map求值;std::vectorvecfiles={“file1”、“file2”、“file3”};
对于(自动i=0;istrad在您的场景中存在大量内存开销:

  • 您将每个文件行存储为一个单独的
    std::string
    对象。每个这样的对象本身占用一些空间(在64位体系结构中通常为24或32字节),但是,仅当字符串较短且应用了小/短字符串优化(SSO)时,存储的字符串(行字符)才会存储在其中(通常是由C++11中的公共标准库实现实现实现的)。如果行很长,则动态分配字符串的空间,并且每次分配都会有一些额外的内存开销
  • 您将
    这些
    std::string
    对象推回
    std::vector
    ,这通常会以指数方式增加内部缓冲区的大小(例如,当空间用完时将其加倍)。这就是保留空间的原因(
    std::vector::reserve
    )当您提前知道向量元素的数量时,使用
  • 这是这种“舒适”方法的代价。可能有帮助的是将整个文件内容存储为单个
    std::string
    ,然后将索引/指针存储到单独数组/向量中的各行开头(尽管您不能将这些指针视为字符串,因为它们不会以null结尾;或者,如果您用null字符替换新行字符,您实际上可以这样做)

    在C++17中,可以将行作为
    std::string\u视图的实例存储到单个
    std::string
    中存储的整个文件内容中

    请注意,
    std::string_视图
    可能比指针/索引大。例如,对于libstdc++和x86_64,
    sizeof(std::string_视图)
    是16个字节,但指针/索引将占用8个字节。对于小于4 GB的文件,甚至可以使用32位索引。如果处理的文件中有很多行,这些差异可能很重要

    更新


    这个问题非常相关:.

    与您的问题完全无关,但是为什么字符串流
    strad
    ?为什么不直接使用
    vecFile[i]
    ?您甚至不需要
    path
    变量(如果您使用
    read\u file
    取而代之的是
    const
    引用,您确实应该这样做).std::vector a=read_文件(路径)的可能重复;求值[strad.str()]=a;
    如果是副本,您可以移动它(实际上您可以使用移动插入)。一堆文件在抽屉里不会占用太多空间,但找到你想要的文件却非常慢。为有效定位而组织的一堆文件将占用更多空间。一个
    std::string
    将有一些开销。文件中的很多行将意味着大量
    std::string
    s和更多开销。你应该我可以通过使用
    std::vector
    来减少一些开销,但我不确定这是否是您想要做的事情。我将尝试实施这些建议,并接受有效的答案。如果您有一个示例,主要针对第2点)(我不确定第1点会释放大量内存,因为我没有很多文件)是的great@froz第1点)可能也会节省大量内存,可能比第2点多得多)。我会将整个文件读入单个
    std::string
    ,在计算行数时用空字符替换新行字符,然后使用该计数器为向量索引保留空间,最后再次传递并存储索引xes。这两种结构(包含文件内容的字符串和索引向量)是
    read_file
    函数的结果。@froz顺便说一句,重要的不是文件的数量,而是每个文件中的行数。
    std::map<std::string, std::vector<std::string>> buildmap(std::string folder){
        std::map<std::string,std::vector<std::string>> evaluations; std::vector<std::string> vecFiles = {"file1","file2","file3"};
        for( auto i = 0; i < vecFiles.size(); i++ )
        {
            std::stringstream strad;
            strad <<vecFiles[i] ;
            std::string path(folder+vecFiles[i]);
            std::vector<std::string> a = read_file(path);
            evaluations[strad.str()]=a;
        }
        return evaluations;   
    }