创建大量对象指针
creating large number of object pointers
我定义了一个 class 这样的:
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 万行。在这些情况下,程序会非常慢。您有什么建议可以让它更快吗?
首先,找到比标准流更快的 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))
{}
这会对长名称产生影响。 None 由于 "small string optimization"。
第四,停止制作指针向量。创建值向量。
第五,失败后,找到一种更有效的方法来 allocate/deallocate 对象。
您可以做的一件事是直接将您从文件中读取的 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
需要在下一行读取,并避免任何额外的 allocations/copying .与往常一样,在您有理由关心时进行衡量。
你可能会通过预先为你的向量保留 space 获得一个小的胜利,尽管你在向量中存储指针而不是按值 存储 myClass 对象 使任何调整大小的矢量都相对便宜。与此相反,存储指针确实意味着您正在进行额外的动态分配。
您可以做的另一件事是增加流缓冲区大小:请参阅 pubsetbuf
和其中的示例。
如果速度非常重要,您应该内存映射文件并将指针存储到内存映射区域,而不是从文件流缓冲区复制到不同字符串内的不同动态分配的内存区域。这很容易产生显着差异 - 可能高达一个数量级 - 但很大程度上取决于磁盘速度等。因此,如果你有理由关心,请对两者进行基准测试。
我定义了一个 class 这样的:
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 万行。在这些情况下,程序会非常慢。您有什么建议可以让它更快吗?
首先,找到比标准流更快的 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))
{}
这会对长名称产生影响。 None 由于 "small string optimization"。
第四,停止制作指针向量。创建值向量。
第五,失败后,找到一种更有效的方法来 allocate/deallocate 对象。
您可以做的一件事是直接将您从文件中读取的 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
需要在下一行读取,并避免任何额外的 allocations/copying .与往常一样,在您有理由关心时进行衡量。
你可能会通过预先为你的向量保留 space 获得一个小的胜利,尽管你在向量中存储指针而不是按值 存储 myClass 对象 使任何调整大小的矢量都相对便宜。与此相反,存储指针确实意味着您正在进行额外的动态分配。
您可以做的另一件事是增加流缓冲区大小:请参阅 pubsetbuf
和其中的示例。
如果速度非常重要,您应该内存映射文件并将指针存储到内存映射区域,而不是从文件流缓冲区复制到不同字符串内的不同动态分配的内存区域。这很容易产生显着差异 - 可能高达一个数量级 - 但很大程度上取决于磁盘速度等。因此,如果你有理由关心,请对两者进行基准测试。