0

我正在编写一个程序,我有一个类,在该类内部(或外部,希望没关系)我有结构。在那个类中,我需要创建一个结构元素数组(我知道我可以使用向量,例如,但在程序中只允许使用简单的动态数组)。

我将一个数组声明为T * arr[SIZE]T我的结构在哪里。唯一的问题是我不知道数组的确切大小,如有必要需要增加它的大小。所以我写了函数来调整它的大小:

if( some cond ){
    T * tmpArr[newSIZE];
    memcpy( tmp, db, newSIZE*sizeof(T));
    delete [] arr;
    arr = tmpArr;
}

但是我遇到了一个与我猜想的表达MyClass::T[....]方式不兼容的错误。MyClass::T*[SIZE]arr = tmpArr

你能告诉我我做错了什么吗?在这种情况下,如何更好地声明T * arr[size]T * arr = new T[size]如何调整数组的大小(并从旧数组中释放内存)?

更新:

感谢您的回答,我在我的程序中做了相应的操作:

    T * tmp = new T[newSIZE];
    memcpy( tmp, db, newSIZE*sizeof(T) );
    delete [] db;
    db = tmp;

现在我得到了奇怪的东西,在删除 db 并分配dbtmp我尝试打印包含在 db (或 tmp )中的所有数据之后,我得到了奇怪的东西:

   Smith2 Michigan ave▒ ACME, Ltd. One ACME roa▒
   Smit▒ Michigan ave` ACME, Ltd. One ACME roa "

   One ACME road#@"▒▒▒▒Michigan ave`▒▒▒▒Smit▒"

   ▒▒ ▒8 Ltd.#Michigan avenuemith4▒aF▒

如果我在删除和分配之前打印相同的数据,我会得到我想要的普通文本。在程序中之后(因为我以前没有,也许这是我的代码的问题,我得到分段错误)。顺便说一句,我在我的 Windows 中使用struct了 ofstd::string和 cygwin。你知道这里有什么问题吗?

4

5 回答 5

4

T* tmpArr[newSIZE];声明一个可变长度的指针数组T。请注意,可变长度数组不是标准 C++ 的一部分(它们是 C99 的一部分,但在 C++ 中只能作为 GCC 的扩展......因此,此代码无法使用不同的编译器编译)。

完全合理的解决方案是使用std::vector,但既然你自己写了不允许使用它,那么这就是你可以做的。

  1. 更改T* tmpArr[newSIZE];T* arr = new T[size];
  2. 现在调整这个数组的大小:
    1. 分配新数组:T* newArr = new T[newSize]
    2. 从旧数组复制元素:memcpy(newArr, arr, size * sizeof(T))
    3. 使用以下方法释放旧数组delete[]delete[] arr
    4. 由于delete不会更改指针本身,因此在第 3 步之后您的指针无效(悬空),因此将指向新数组第一个元素的指针分配给旧数组:arr = newArr
  3. 跟踪您正在使用的数组的大小

请注意,T* arr = new T[size]分配足够大的内存以容纳size类型的T对象,并使用T. 然后分配第一个元素的地址,arr使其指向这些元素所在的连续内存块。

于 2013-03-25T19:50:39.343 回答
3
T arr[N];

这种形式的声明为您提供了一个N具有自动存储持续时间的大小数组。这是固定的。您无法更改此数组的大小。大小N必须是编译时常量。

T* arr = new T[N];

这个声明定义了一个T*带有自动存储的持续时间。但是,它还创建了一个N具有动态存储持续时间的大小数组。在这里,大小N不需要是编译时常量。

但是,这对您没有帮助。您仍然无法调整动态数组的大小。您必须delete[] arr销毁旧数组,然后new T[NewSize]以某种方式复制数据。

这肯定会变得一团糟,事实上确实如此。在您的代码中,您混合了两种不同类型的分配。delete[] arr即使arr没有动态存储持续时间,您也正在尝试这样做。你根本无法做到这一点。您也不能将一个数组分配给另一个数组,如arr = tmpArr;.

相反,C++ 标准库提供了许多称为容器的类型。这些使得动态调整大小的元素序列变得非常容易。例如,您最好使用std::vector<T>.

std::vector<T> arr;

Astd::vector开头没有元素。您可以通过简单地添加元素arr.push_back(value)。您还可以通过执行非常轻松地一次性调整矢量大小arr.resize(newSize)

于 2013-03-25T19:41:14.817 回答
1

我猜您正在尝试删除您创建的数组,如下所示:

T array[size];

但是您不应该对此调用 delete 。当超出范围时,该数组将被删除。如果要创建一个数组并在之后释放它,则必须new在声明数组时使用运算符。如果您想释放它,请使用delete.

但无论如何,您可能想使用std::vector而不是尝试自己做。如果你有兴趣了解这些东西,这里有一个来自 Microsoft 的频道 9 视频系列,作者是 Stephen T. Lavavej:

http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Standard-Template-Library-STL-/C9-Lectures-Introduction-to-STL-with-Stephan-T-Lavavej这是一颗真正的宝石。

于 2013-03-25T19:40:58.567 回答
0

简单的解决方案不是重新发明方轮,而是使用std::vector<Type>标准库中已经圆形和抛光的模板。

于 2013-03-25T19:41:45.487 回答
0

我会假设您实际上想要存储指向T. 你需要:

  • 添加一个缺失的*,因为您正在分配一个指针数组T
  • 删除大小tmpArrarr

所以:

// arr definition
 T **arr;;

// arr resizing code
if( some cond ){
    T **tmpArr;
    memcpy( tmp, db, newSIZE*sizeof(T *));
    delete [] arr;
    arr = tmpArr;
}

您的数组存储指向T、 not的指针T,并且tmpArr在编译时不知道大小,因此您无法在其类型中指定它。

警告:如果新大小小于当前大小,您将丢失数组末尾的指针。你应该在上面添加一个测试,并删除这些额外的T(如果你的容器拥有它们),或者只是抛出一个异常,因为代码只应该增加数组的大小。

于 2013-03-25T20:10:20.467 回答