我遇到了一些实现解决方案的问题,该解决方案在循环中处理堆上的对象创建并将其存储在数组中。
我有一个代表共享交易的交易类。它包括自定义日期和时间类以及一些用于存储数值的双精度值。
我使用包含大约100条交易记录的CSV文件中的TransactionIO类读取这些内容。
我的算法如下:
While EOF not reached
Read Transaction data
Create Transaction object on heap
Return pointer to newly created Transaction object
Store 'Pointed-to-Transaction' in custom Vector
EndWhile
以下是TransactionIO函数ReadTransaction的代码:
// Reads in a transaction and returns it
Transaction* TransactionIO::ReadTransaction(ifstream& is)
{
// Assuming file structure is a CSV file
// With structure given as:
// Date/Time, Price, Volume, Value, Condition
Date date;
Time time;
double price, volume, value;
string condition;
string dateString, timeString;
//cout << "\nBegin Read..." << endl;
getline(is, dateString, ','); // read date/time string and then parse
ReadNextDoubleField(price, is);
ReadNextDoubleField(volume, is);
ReadNextDoubleField(value, is);
getline(is, condition);
// split the date and time fields and parse them
timeString = dateString.substr(dateString.find_first_of(" ") + 1);
dateString.erase(dateString.find_first_of(" ")); // remove the time string - only need date string here
date = ParseDate(dateString); // Will change later to use pass by reference
time = ParseTime(timeString); // Will change later to use pass by reference
// construct and return transaction that was read
Transaction* transaction = new Transaction(date, time, price, volume, value, condition);
return transaction
}
我还没有创建我的主类,因为我正在处理我的数据类。那么使用这个函数的正确方法是什么?
我打算这样做:
在main中的循环:
While(//file IO condition here...)
{
p_transaction = TransactionIO::ReadTransaction(is);
myCustomVector.Add(*transaction);
}
这是正确的方法吗?我的自定义向量的Add方法需要const T&amp;引用添加给定对象。
另外,在我的自定义矢量的内部数组上调用delete []会删除存储在其中的对象吗?
我觉得我的代码非常低效,我的讲师警告我不要在循环中构造对象。我应该通过引用返回对象。
但在这种情况下,如果我尝试过这不会无效吗?
void TransactionIO::ReadTransaction(Transaction& transaction, ifstream& is)
{
// Do all the reading and processing as given above....
Transaction t1(date, time, price, volume, value, condition);
transaction = t1; // creating object AND call assignment op - not efficient?
}
在上面一行中,一旦此函数完成,t1将超出范围,对象将被销毁。那么我的参考指向什么呢?
这就是为什么我决定使用指针解决方案,但我觉得我的程序会有很大的内存泄漏......
我们非常感谢任何帮助和解释......如果可能的话,我不仅想知道“如何”,还要知道答案的“原因”。
最后,没有。我不能使用STL容器。我必须使用自己的矢量类(我已经测试过它并且效果很好。)
答案 0 :(得分:0)
如果长时间运行,在循环中分配对象效率很低。
您可以做的一件事是预先分配您的矢量,但如果您不知道所需的大小,它也可能效率低下。 在STL中你可以使用reserve:http://www.cplusplus.com/reference/vector/vector/reserve/ 但在你的情况下,你需要在vector类中实现类似的东西。
在上面一行中,一旦这个功能完成,t1就会消失 范围和对象将被销毁。那么我的参考是什么呢 指向? 未定义的行为,除非Transaction是某种智能指针。
此外,将在我的自定义矢量的内部数组上调用delete [] 删除存储在其中的对象?
如果我理解得很好,是的。
因此,您可以保留向量的大小(如果您具有良好的估计大小),然后填充已创建的插槽。 这样你的矢量就不需要如此频繁地扩大尺寸。
答案 1 :(得分:0)
我同意你最好堆叠分配你的对象。
堆分配比较昂贵,在您的情况下是不必要的,因为在将对象复制到向量之前,您只使用指针作为临时存储。然后你需要删除那些我不认为你做的指针。
就此而言:
void TransactionIO::ReadTransaction(Transaction& transaction, ifstream& is)
{
// Do all the reading and processing as given above....
Transaction t1(date, time, price, volume, value, condition);
transaction = t1; // creating object AND call assignment op - not efficient?
}
您没有将transaction
变为t1
的引用,而是将t1
的内容分配给transaction
引用的对象。您甚至可以transaction = std::move(t1);
显式使用移动赋值运算符(只要您定义了一个或您的类符合隐式定义的规则)并且无需复制。
但是,您甚至不需要传入引用,如果您只是按值返回,编译器将忽略该副本,而是直接分配到调用站点。这称为Return Value Optimisation。因此,您可以执行以下操作:
Transaction TransactionIO::ReadTransaction(ifstream& is)
{
// Do all the reading and processing as given above....
return Transaction(date, time, price, volume, value, condition);
}
或者在C ++ 11中:
Transaction TransactionIO::ReadTransaction(ifstream& is)
{
// Do all the reading and processing as given above....
return {date, time, price, volume, value, condition};
}