用于调整数组大小的模板

时间:2017-07-12 23:27:37

标签: c++ arrays string templates

我正在尝试编写一个包含一类数组函数的模板类。 我把一些东西放在一起似乎适用于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;
}

提前谢谢。

2 个答案:

答案 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;
}

关键点:

  • 如果尺寸与以前相同,则没有调整尺寸!
  • 您只能复制一次,并通过标准的memcpy
  • 此功能与类型无关,可用于所有模板调整大小功能
  • 当调整大小的数组较大时,内存使用memset()进行处理,以避免内存泄漏