调整指针数组的大小,没有内存泄漏

时间:2016-01-03 21:26:36

标签: c++ arrays pointers object

我有一个指向对象指针数组的指针,需要调整数组大小。我确实知道这是使用矢量的最佳时机,但我不允许这样做。我的代码有效,但我并不完全遵循我所写的内容,并担心我可能会造成内存泄漏:

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];

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

2 个答案:

答案 0 :(得分:1)

*transfer[i] = *sets[i];

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

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

答案 1 :(得分: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的内存也会泄漏。如果您在transfer之前将delete[] sets直接分配给最终大小,如果这将被抛出,sets将保持不变,transfer将不会泄漏(因为它在分配期间丢失,即没有分配)。

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