C++ 创建映射时如何管理内存<;字符串,向量<;字符串>&燃气轮机;通过读取文件
我想知道当不同的文件存储在字符串向量的映射中时,内存是如何管理的。 我曾尝试读取不同的文件,每个文件的内存为10个月,当我使用KSySGuard检查内存时,显示的内存是我的文件内存的两倍多(~70mo)。 我为您提供了一个代码示例: 有一个函数readfile():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))
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;i strad在您的场景中存在大量内存开销:
您将每个文件行存储为一个单独的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;
}