[英]how to double array size (error on second time)
这里有一些帮助,试图在 cpp 中加倍数组
在第二次调整大小时我得到了这个(混乱的输出)
% ./sample
[5] 1 2 3 4 5
[20] 1 2 3 4 0 6 7 -1610612736 1 2 3 4 14 0 0 0 0 -1610612736 0 0
同样删除内存集(将剩余位置归零)
#include <iostream>
#include <cstdlib>
using namespace std;
void resize(int* v, int* size){ // double the array size
int newSize = (*size) * 2;
v = (int *) realloc(v, (size_t) newSize);
memset(v+(*size), 0, sizeof(int) * (newSize - *size) );
*size = newSize;
}
int main(){
int size = 5;
int* v = new(nothrow) int[size]();
v[0] = 1; v[1] = 2; v[2] = 3; v[3] = 4; v[4] = 5;
cout << "[" << size << "] ";
for(int i = 0; i < size; i++) cout << v[i] << " "; cout << endl;
resize(v, &size);
resize(v, &size); // <- messy output
v[5] = 6; v[6] = 7;
cout << "[" << size << "] ";
for(int i = 0; i < size; i++) cout << v[i] << " "; cout << endl;
return 0;
}
谢谢您的帮助,
将malloc()
与realloc()
或new
和delete[]
一起使用 - 不能同时使用
您的直接问题是您将指针传递给 function 并且 function 收到一个副本 - 因此对 function 中的v
所做的任何更改都会对指针的本地副本进行(它有自己的地址并且与指针v
非常不同在main()
)
另一个问题是混合使用new
和realloc()
,这会导致未定义的行为。 在main()
中使用malloc()
) 或使用new
在您的 function 中手动创建和复制,并在分配新块之前在原始对象上调用delete[]
。
由于这是 C++,您可以通过将指针引用传递给 function(例如int*& v
)来轻松解决问题,因此realloc()
对原始指针地址而不是副本进行操作。
注意:正如 JL 在评论中提到的,每当您调用realloc()
时,您必须将结果分配给一个临时指针,您在分配给原始指针之前验证realloc()
是否成功。 当(不是如果) realloc()
失败时,它将返回NULL
并用 NULL 覆盖您的原始指针,从而使NULL
的块无法释放,从而造成 memory 泄漏。
要将临时指针与realloc()
一起使用,您可以这样做:
void resize(int*& v, int *size){ // double the array size
int newSize = (*size) * 2;
/* always realloc with temporary pointer so if realloc fails
* you don't overwrite your orignal pointer with NULL creating
* a memory leak.
*/
int *tmp = (int *)realloc (v, (size_t) newSize * sizeof *v);
if (!tmp) { /* validate every allocation */
perror ("realloc-v");
return;
}
v = tmp; /* successful realloc(), assign tmp to v */
memset (v+(*size), 0, sizeof(int) * *size );
*size = newSize;
}
此外,在main()
中要使用realloc()
,您最初必须使用malloc()
(或calloc()
或realloc()
,但不是new
)进行分配。 此外,保护您的循环范围,或者如果您不打算使用{...}
保护 scope,那么至少适当缩进以便您的意图明确,例如
int main(){
int size = 5;
int *v = (int*)malloc(size * sizeof *v);
v[0] = 1; v[1] = 2; v[2] = 3; v[3] = 4; v[4] = 5;
cout << "[" << size << "] ";
for (int i = 0; i < size; i++)
cout << v[i] << " ";
cout << endl;
resize(v, &size);
resize(v, &size);
if (size > 6) { /* validate size / protect memory bounds */
v[5] = 6;
v[6] = 7;
}
cout << "[" << size << "] ";
for (int i = 0; i < size; i++)
cout << v[i] << " ";
cout << endl;
return 0;
}
(您还应该为memset()
添加#include <cstring>
)
使用new
和delete[]
如果您使用new
在 function 中创建一个大小加倍的新块,则可以将分配保留在main()
中,将值复制到新块(并将 rest 初始化为0
)并在原始块上调用delete[]
在将新块分配给原始指针之前阻塞。
在那种情况下,你会做类似的事情:
void resize(int*& v, int *size){ // double the array size
int newSize = (*size) * 2;
/* create a new block of newSize */
int *tmp = new(nothrow) int[newSize]();
/* copy/initialize */
for (int i = 0; i < newSize; i++) {
if (i < *size)
tmp[i] = v[i];
else
tmp[i] = 0;
}
delete[] v; /* free original block */
v = tmp; /* assign tmp to v */
*size = newSize;
}
示例使用/输出
在任一情况下( malloc()
、 realloc()
)或( new
、 delete[]
),结果都是相同的:
$ ./bin/realloc_arr
[5] 1 2 3 4 5
[20] 1 2 3 4 5 6 7 0 0 0 0 0 0 0 0 0 0 0 0 0
在这两种情况下,您都需要验证您的 memory 使用valgrind
或类似的 memory 使用/错误检查您的操作系统。 您需要在main()
的末尾添加free(v)
或delete[] v
来处理释放您为 memory 检查目的分配的所有 883933302533388(它将在程序退出后释放,但没有明确说明在main()
中释放它仍然会在程序退出时显示为正在使用。
要使用 valgrind,只需通过它运行您的程序。 进行上述更改后,您将拥有:
$ valgrind ./bin/realloc_arr
==22674== Memcheck, a memory error detector
==22674== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==22674== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==22674== Command: ./bin/realloc_arr
==22674==
[5] 1 2 3 4 5
[20] 1 2 3 4 5 6 7 0 0 0 0 0 0 0 0 0 0 0 0 0
==22674==
==22674== HEAP SUMMARY:
==22674== in use at exit: 0 bytes in 0 blocks
==22674== total heap usage: 5 allocs, 5 frees, 73,868 bytes allocated
==22674==
==22674== All heap blocks were freed -- no leaks are possible
==22674==
==22674== For counts of detected and suppressed errors, rerun with: -v
==22674== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始终确保释放所有块并且没有 memory 错误。
供参考工作版本
#include <iostream>
using namespace std;
void resize(int*& v, int* size){ // double the array size
int newSize = (*size) * 2;
int* tmp = new(nothrow) int[newSize](); // zeroing on the next line is redundant?
for(int i = 0; i < newSize; i++) tmp[i] = (i < *size) ? v[i] : 0;
delete[] v;
v = tmp;
*size = newSize;
}
int main(){
int size = 5;
int* v = new(nothrow) int[size]();
v[0] = 1; v[1] = 2; v[2] = 3; v[3] = 4; v[4] = 5;
cout << "[" << size << "] ";
for(int i = 0; i < size; i++) cout << v[i] << " "; cout << endl;
resize(v, &size);
resize(v, &size); // <- NOW, working output
//resize(v, &size);
v[5] = 6; v[6] = 7;
cout << "[" << size << "] ";
for(int i = 0; i < size; i++) cout << v[i] << " "; cout << endl;
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.