我已经定义了这样一个类:
class myClass {
private:
int count;
string name;
public:
myClass (int, string);
...
...
};
myClass::myClass(int c, string n)
{
count = c;
name = n;
}
...
...
我还有一个* .txt文件,每行都有一个名称:
David
Jack
Peter
...
...
现在我逐行读取文件并为每一行创建一个新的对象指针,并将所有对象存储在一个向量中。功能是这样的:
vector<myClass*> myFunction (string fileName)
{
vector<myClass*> r;
myClass* obj;
ifstream infile(fileName);
string line;
int count = 0;
while (getline(infile, line))
{
obj = new myClass (count, line);
r.push_back(obj);
count++;
}
return r;
}
对于小* .txt文件我没问题。但是,有时我的* .txt文件包含超过100万行。在这些情况下,该程序非常缓慢。你有什么建议让它更快吗?
答案 0 :(得分:2)
首先,找到比标准流更快的io。
其次,您可以使用字符串视图而不是字符串吗?它们是C ++ 17,但到处都有C ++ 11及更早版本。
第三,
myClass::myClass(int c, string n) {
count = c;
name = n;
}
应该阅读
myClass::myClass(int c, std::string n):
count(c),
name(std::move(n))
{}
这会对长名称产生影响。由于&#34;小字符串优化&#34;。
,因此没有简短的第四,停止制作指针向量。创建值的向量。
第五,如果不这样做,找到一种更有效的方式来分配/解除分配对象。
答案 1 :(得分:1)
您可以做的一件事就是直接将您从文件中读取的string
移动到您正在创建的对象中:
myClass::myClass(int c, string n)
: count{c}, name{std::move(n)}
{ }
您还可以进行基准测试:
myClass::myClass(int c, string&& n)
: count{c}, name{std::move(n)}
{ }
上面的第一个版本将在调用函数时生成line
的副本,然后让myClass
对象接管用于该副本的动态分配的缓冲区。第二个版本(带有string&& n
参数)将让myClass
对象直接删除line
的缓冲区:这意味着更少的文本数据复制,但行也可能被删除读取文件的每一行时都要使用缓冲区。希望您的分配通常能够从输入缓冲区中看到下一行中需要读取的容量line
的大小,并避免任何额外的分配/复制。一如既往,在您有理由关注时进行衡量。
你可能会通过预先为你的向量预留空间来获得一个小胜利,尽管你在向量中存储指针而不是按值存储myClass对象的事实会使任何向量调整大小相对便宜。反驳说,存储指针确实意味着你正在进行额外的动态分配。
您可以做的另一件事是增加流缓冲区大小:请参阅pubsetbuf
及其中的示例。
如果速度非常重要,则应该对内存映射文件并将指针存储到内存映射区域,而不是从文件流缓冲区复制到不同字符串内的不同动态分配的内存区域。这可能很容易产生显着的差异 - 可能多达一个数量级 - 但很大程度上取决于你的磁盘的速度等。所以如果你有理由去关注它们的基准。