我有一个指向对象指针数组的指针,需要调整数组大小。我确实知道这是使用矢量的最佳时机,但我不允许这样做。我的代码有效,但我并不完全遵循我所写的内容,并担心我可能会造成内存泄漏:
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];
如果我想在以后使用删除功能释放这些对象,我是否需要担心?
答案 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
(也许还有指针,以防你的集合拥有它们)。