【问题标题】:resize an array of pointers without memory leak在没有内存泄漏的情况下调整指针数组的大小
【发布时间】:2016-04-07 12:18:26
【问题描述】:

我有一个指向对象指针数组的指针,并且需要调整数组的大小。我确实意识到这是使用向量的最佳时机,但我不允许这样做。我的代码有效,但我没有完全按照我写的内容进行操作,并且担心我可能会造成内存泄漏:

void foo (DataSet &add_data)
{
    if (sets == NULL)
    {
        sets = new DataSet*[1];
        sets[0] = &add_data;
    }
    else
    {
        DataSet **transfer;        
        transfer = new DataSet*[num_of_sets];       

        for (int i = 0; i < num_of_sets; i++) // Copy addresses?
            transfer[i] = sets[i];     

        delete [] sets; // Free the array.        
        sets = new DataSet*[num_of_sets + 1]; // Create new sets  

        for (int i = 0; i < num_of_sets; i++) // Copy back
            sets[i] = transfer[i];            

        sets[num_of_sets] = &add_data;        // Add the new set        
        delete [] transfer;
        transfer = NULL;
    }    
    num_of_sets++;
}

Visual Studio 为什么会抛出异常:

for (int i = 0; i < num_of_sets; i++) // Copy addresses?
    *transfer[i] = *sets[i];

但不是:

for (int i = 0; i < num_of_sets; i++) // Copy addresses?
    transfer[i] = sets[i];

但是这两个代码段在 linux 中编译和运行都没有错误。此代码应复制指向对象的指针。是这样的吗:

for (int i = 0; i < num_of_sets; i++) // Copy addresses?
    transfer[i] = sets[i];

如果我想稍后使用删除功能释放这些对象,我是否需要担心?

【问题讨论】:

  • std::vector&lt;std::unique_ptr&lt;DataSet&gt;&gt;.
  • 我不能使用矢量...我知道 :(
  • 为什么现在没有人使用矢量了?
  • @JameyD,通常这是一项误导性任务的一部分,旨在通过禁止使用标准库来教授一个“真正的”c++。
  • @StoryTeller 而不是 C99。对于一直使用原始指针而不是智能指针的每个人以及一直在教授使用原始指针的教师也是如此。

标签: c++ arrays pointers object


【解决方案1】:

你不需要分配两次,只分配一次最终大小:

    transfer = new DataSet*[num_of_sets + 1]; // Create new sets - final size

    for (int i = 0; i < num_of_sets; i++) // Copy addresses?
        transfer[i] = sets[i];

    delete [] sets; // Free the array.

    sets = transfer;

    sets[num_of_sets] = &add_data;        // Add the new set
    // now no need to delete[] transfer

顺便说一句,您还可以获得改进的异常安全性。 - 在您的原始代码中,您在将新数据分配给它之前删除了sets - 如果这会抛出std::bad_alloc,那么不仅您的对象会变得不一致(有一个悬空的sets ptr,因为您没有将null分配给它在删除后)但分配给transfer的内存也会泄漏。如果您在delete[] sets 之前将transfer 直接分配到最终大小,如果这会抛出,sets 将保持不变并且transfer 不会泄漏(因为它在分配期间抛出,即没有分配)。

当然,请确保您在析构函数中使用了 delete[] sets(也可能还有指针,以防您的集合拥有它们)。

【讨论】:

  • 是的,我很清楚我的析构函数中的delete [] sets
【解决方案2】:
*transfer[i] = *sets[i];

不复制地址,就像其他示例(没有星号)一样,它尝试取消引用 transfer 的未初始化指针元素并在这些地址上的 DataSet 对象上调用 operator=

这是未定义的行为,这就是为什么它似乎在变化的环境下工作。

【讨论】:

  • 这就是我的想法......但我有疑问,因为传输和集合都是指向指针数组的指针,也许我需要在该数组中指定值(取消引用)。
  • [] 是第一次取消引用,* 是第二次取消引用。由于您有指向指针的指针并且想要复制指向的指针,因此您只需要一个取消引用。
  • 谢谢...现在说得通了!
  • @Michael 顺便问一下,是否希望您的函数只管理一个指针数组,并且对这些指针指向的对象的生命周期一无所知?
  • 是的。如果我理解你的问题是正确的。这些对象不应该在它们被实例化的类之外被释放。编辑:也许我应该做一个 NULL 检查......嗯......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-20
  • 2018-02-14
  • 1970-01-01
  • 2021-12-19
  • 1970-01-01
  • 2012-03-17
  • 1970-01-01
相关资源
最近更新 更多