我正在尝试编写一个包含一类数组函数的模板类。 我把一些东西放在一起似乎适用于int,float,double,但不适用于字符串。我包括,并使用命名空间标准。
Everything编译,并且除非我使用字符串,否则工作正常,在这种情况下,它会在resize函数中出错。
在头文件中我有以下相关代码(因为所有内容都编译,错误只存在于此处):
template<typename T>
void Array<T>::resize(int newSize)
{
T* newArray = new T[newSize];
if (newSize >= mSize)
{
for (int i = 0; i < newSize; ++i)
newArray[i] = mData[i];
}
else
for (int i = 0; i < mSize; ++i)
newArray[i] = mData[i];
delete[] mData;
mData = new T[newSize];
mSize = newSize;
for (int i = 0; i < newSize; ++i)
mData[i] = newArray[i];
delete[] newArray;
newArray = 0;
}
提前谢谢。
答案 0 :(得分:0)
看看这段代码:
T* newArray = new T[newSize];
if (newSize >= mSize)
{
for (int i = 0; i < newSize; ++i)
newArray[i] = mData[i];
}
请注意,如果新大小大于旧大小,则从旧数组中读取值从0到newSize
进行迭代。问题是旧数组只有从0到mSize - 1
有效的索引,而不是从0到newSize - 1
,所以这会读取数组的末尾。这会在所有情况下导致未定义的行为(oops!),但对于基本类型,这通常不会导致崩溃,您只能看到这个字符串。
您可能希望查看其余代码以确保循环边界正确,因为我认为您至少会发现一个未正确设置的循环。
另外,请考虑使用像valgrind
这样的工具,这些工具非常适合诊断这些内存错误。
作为一个完整的偶然发现,您可能还想考虑是否需要进行两次分配和两次解除分配。你能用一个新的分配和一个释放来做到这一点吗?
答案 1 :(得分:0)
假设mData
的类型为T*
,您可以尝试以下内容:
template<typename T>
void Array<T>::resize(int newSize)
{
if (newSize == mSize) {
return;
}
T* newArray = new T[newSize];
if (newSize < mSize) {
memcpy(newArray, mData, newSize * sizeof(T));
} else {
memset(newArray, 0, mSize * sizeof(T));
memcpy(newArray, mData, mSize * sizeof(T));
}
delete[] mData;
mData = newArray;
mSize = newSize;
}
关键点: