如何有效地管理数组(C ++)中的堆对象?

时间:2015-02-11 10:38:58

标签: c++ arrays pointers

我遇到了一些实现解决方案的问题,该解决方案在循环中处理堆上的对象创建并将其存储在数组中。

我有一个代表共享交易的交易类。它包括自定义日期和时间类以及一些用于存储数值的双精度值。

我使用包含大约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容器。我必须使用自己的矢量类(我已经测试过它并且效果很好。)

2 个答案:

答案 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};
}