如何有效地管理数组中的堆对象(C++)
How to efficiently manage heap objects in array (C++)?
我在实现一个解决方案时遇到了一些问题,该解决方案在循环中处理堆上的对象创建并将其存储在数组中。
我有一个代表股票交易的交易类。它包括自定义的日期和时间类,以及一些用于存储数值的双值。
我使用TransactionIO类从一个包含大约100条事务记录的CSV文件中读取这些。
我的算法如下:
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
}
我还没有创建我的主类,因为我正在处理我的数据类。那么,使用这个函数的正确方法是什么呢?
我正计划这样做:
主回路中:
While(//file IO condition here...)
{
p_transaction = TransactionIO::ReadTransaction(is);
myCustomVector.Add(*transaction);
}
这样做对吗?我的自定义向量的Add方法需要一个常量T&引用以添加给定对象。
此外,对自定义向量的内部数组调用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容器。我必须使用我自己的向量类(我已经测试过了,效果很好。)
我同意您最好通过堆栈分配对象。
堆分配相对昂贵,在您的情况下是不必要的,因为在将对象复制到向量中之前,您只将指针用作临时存储。然后你需要删除那些指针,我看你不会这么做。
在这种情况下:
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);
显式地使用移动赋值运算符(只要您定义了一个或您的类符合隐式定义的规则),并消除对副本的需要。
然而,您甚至不需要传入引用,如果您只是按值返回,编译器将删除副本,而不是直接分配到调用站点。这就是所谓的回报价值优化。因此,您可以执行以下操作:
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};
}
如果循环运行时间很长,那么在循环中分配对象的效率很低。
你可以做的一件事是预先分配你的向量,但如果你不知道你需要什么大小,这也可能是低效的。在STL中,您可以使用保留:http://www.cplusplus.com/reference/vector/vector/reserve/但在您的情况下,您需要在向量类中实现类似的东西。
在上面的行中,一旦该函数完成,t1将退出范围和对象将被销毁。那么我的参考资料是什么指向?未定义的行为,除非Transaction是某种智能指针。
此外,将对自定义向量的内部数组调用delete[]删除存储在其中的对象?
如果我理解得很好,是的。
因此,您可以保留向量的大小(如果您有一个很好的估计大小),然后填充已经创建的槽。这样,矢量就不需要如此频繁地扩展大小。
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- CMake-按正确顺序将项目与C运行时对象文件链接
- 空基优化子对象的地址
- 将对象数组的引用传递给函数
- 你能重载对象变量名本身返回的内容吗
- C++使用整数的压缩数组初始化对象
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 将对象移动到std::shared_ptr
- 代理对象的常量正确性
- 提升 ASIO 无法识别计时器对象
- 将Ref对象作为类成员
- 将包含C样式数组的对象初始化为成员变量(C++)
- 如何返回一个类的两个对象相加的结果
- 使用std::函数映射对象方法
- 是否需要删除包含对象的"pair"?
- 如何在自删除后将对象设置为nullptr
- 迭代时从向量和内存中删除对象
- 构造对象的歧义
- 使用"std::unordereded_map"映射到"std::list"对象