假设我想调整一个int指针数组,我有一个看起来像这样的函数
template<typename T>
static void Resize(T* arr, UINT oldsize, UINT newsize) {
T* ret = new T [newsize];
memcpy(ret, arr, sizeof(arr[0]) * oldsize);
delete[] arr;
arr = ret;
};
当我尝试调整使用“new”关键字创建的元素数组时(即使类中的数据本身是POD),问题就开始了,因为delete []会触发它们的解构函数然后离开新数组指向不再存在的对象。所以..即使对象是用“new”创建的,我只能使用free命令摆脱旧数组?或以某种方式删除数组而不触发每个成员的解构函数?
答案 0 :(得分:4)
使用std::vector
。
编辑:根据大众需求,解释为什么OP的代码不起作用。
代码:
template<typename T>
static void Resize(T* arr, UINT oldsize, UINT newsize) {
T* ret = new T [newsize];
memcpy(ret, arr, sizeof(arr[0]) * oldsize);
delete[] arr;
arr = ret;
};
这里arr
是一个按值传递的指针。最后分配给arr
只会更新实际参数的本地副本。所以在这之后,实际的参数,在调用代码中,指向一个已经delete
d的数组,这是一个非常灾难性的结果!
通过引用引用:
,可以获得某种程度的救援template<typename T>
static void Resize(T*& arr, UINT oldsize, UINT newsize) {
T* ret = new T [newsize];
memcpy(ret, arr, sizeof(arr[0]) * oldsize);
delete[] arr;
arr = ret;
};
但这仍然是相当脆弱的代码。
例如,调用者需要跟踪数组大小。
如果std::vector
名为a
,则调整大小调用将显示为
a.resize( newSize )
与DIY解决方案相比,当newSize
更大时,矢量的那些额外元素是无效的(这比将它们作为不确定的值更安全一些)。
std::vector
可以像原始数组一样编入索引。有关如何使用它的更多详细信息,请参阅 C ++教科书。如果你还没有C ++教科书,那就得到一个:对于大多数人来说,从网上学习文章和Q / A来学习C ++是一个不切实际的主张。
答案 1 :(得分:2)
对于它的价值,你要做的事情并不是一件非常糟糕的事情,而且有时它是有意义的,但new
和{{1}提供的界面根本不支持它(或delete
和new[]
)。正如其他人所说,delete[]
,malloc
和free
支持 (需要注意realloc
将复制指针值重新分配,但不保证新区域中的指针被初始化为任何有用的东西,如realloc
)。
所以,不用多说,几乎每个人都能使用的最简单的答案是使用NULL
而不是试图自己管理内存。向量具有调整大小的能力,当它执行时,它将复制需要复制的内容。存在std::vector<int>
以提供“可调整大小的数组”并为您管理内存。实际上,如果你想要一个指针容器,你最好使用std::vector
/ std::vector<std::unique_ptr<T>>
(在C ++ 11中)或来自Boost Pointer Container的东西。
对于它的价值,原始STL没有使用std::vector<std::shared_ptr<T>>
或new[]
来实现delete[]
。通常,操作系统提供的内存远远超出您的要求。例如,如果我尝试std::vector<T>
16个字节,我回来的块可能是1024个字节。我可以使用它来存储四个32位整数。当我用完空间时,我可能要求32个字节,并得到一个1024字节的不同块,我可以将我的四个整数复制到。但是,当原始块实际上足够大以至于开始时,为什么要经历要求新块来保持整数的麻烦?不幸的是,malloc
和new[]
没有提供一种方式来说“给我一个至少这么大的块,顺便说一句,这里的块可能已经够大了。” delete[]
有点。不使用realloc
或new[]
的{{3}}(请注意,它也不使用delete[]
,因为它通常不适用于对象容器;相反,它使用realloc
和非标准函数malloc
)和Facebook Folly includes a std::vector
-like container以类似的方式管理内存。
即便如此,我也不鼓励尝试变得棘手。 malloc_usable_size
有很多满意的用户。
答案 2 :(得分:1)
我认为在删除之前使数组中的所有元素都指向NULL应该完成这项工作。但是如果你可以使用STL那么std :: vector会让你的生活更轻松(正如Alf所说:P)。