如何调整struct元素数组的大小

时间:2013-03-25 19:35:10

标签: c++ arrays pointers dynamic-memory-allocation dynamic-arrays

我正在编写一个程序,我在这个类中有一个类(或者在外面,希望它没关系)我有结构。在那个类中,我需要创建一个struct元素数组(我知道我可以使用vector,但是在程序中它只允许使用简单的动态数组)。

我将数组声明为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并将db分配给tmp之后我尝试打印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▒

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

5 个答案:

答案 0 :(得分: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[]:[{1}}
    4. 取消分配旧数组
    5. 由于delete[] arr不会更改指针本身,因此在步骤3之后您有无效的(悬空)指针,因此将指向新数组的第一个元素的指针指定给旧数组: delete
  3. 跟踪您正在使用的阵列的大小
  4. 请注意arr = newArr分配足够大的内存来保存T* arr = new T[size]类型的size对象,并使用T的默认构造函数构造这些对象。然后将第一个元素的地址分配给T,使其指向连续的内存块,这些元素位于此处。

答案 1 :(得分: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;

std::vector以没有元素开头。您只需执行arr.push_back(value)即可添加元素。您还可以通过arr.resize(newSize)轻松地一次调整矢量大小。

答案 2 :(得分:1)

我猜你试图删除你创建的数组:

T array[size];

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

但无论如何,你可能想要使用std::vector而不是自己尝试。如果你有兴趣了解这些东西,有一个关于来自微软的频道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这是一个真正的宝石。

答案 3 :(得分:0)

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

答案 4 :(得分: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 的指针,而不是T,并且在编译时不知道tmpArr大小,因此您无法在其中指定它类型。

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