我想获取一个大小为N
的数组,并将其缩小为大小为M
的数组,而不会进行不必要的来回复制。以下是否有效?我尝试执行代码,它的工作原理。但我想知道这是否正确,一般而且不依赖于编译器。
int main(int argc, char* argv[]) {
srand(time(NULL));
int N = atoi(argv[1]);
int M = atoi(argv[2]);
double* a = new double[N];
double RANDMAX = RAND_MAX;
std::cout << "Displaying 'a'..." << std::endl;
for (int k=0; k<N; ++k) {
a[k] = rand()/RANDMAX;
std::cout << a[k] << std::endl;
}
double* b = new double[M];
b = a;
delete [] a;
std::cout << "Displaying 'b'..." << std::endl;
for (int k=0; k<M; ++k) {
std::cout << b[k] << std::endl;
}
delete [] b;
}
答案 0 :(得分:5)
b = a;
delete[] a;
在此之后使用b
或a
是UB,因为b
指向与a
相同的数组/位置。它们在赋值后表示相同的数组。因此,当您删除数组两次时,delete[] b;
也是UB。
答案 1 :(得分:3)
你没有泄露最初为b
分配的内存double *b = new double[M];
b = a; // the memory initially pointed by b is lost ...
另外这样你两次删除相同的内存位置(Paranaix已经发布了这个)并且完全没有运气,你的程序一直在运行。
这是一个有效的解决方案
int Num(3), shrunkNum(2);
double *a = (double*)malloc(Num*sizeof(double));
a[0] = 0;
a[1] = 1;
a[2] = 2;
// realloc shrinks memory after copying the contents up to the new size
a = (double*)realloc(a, shrunkNum*sizeof(double));
for (int i(0); i < shrunkNum; ++i)
{
std::cout << a[i] << std::endl;
}
free(a); // how to delete the block pointed by a
请注意realloc
不适用于使用new
分配的内存。
据说我们很少向下重新分配。只需跟踪存在多少元素就足够了。例如,参见STL对向量的作用,其中调整为较小的大小将减小大小,但the capacity remains the same。
答案 2 :(得分:2)
不,如其他地方所述,这段代码是错误的,实际上没有这些操作(新的,删除)的组合可以实现您的目的而不复制数据。
有一个函数realloc()可以完全按照你的意愿执行,但是你应该只在使用malloc()分配的内存上使用它。
诸如vector之类的标准库函数具有重新分配的能力。这是您所描述的首选方式。
答案 3 :(得分:0)
不,你做的是未定义的行为。
首先,您在行double* b = new double[M];
中分配的数组永远不会被释放,因为您在下一行中重新分配了该内存的唯一指针。 (b = a;
)。这是经典的内存泄漏。
其次,在下一行delete [] a;
中删除a
和b
指向的数组。这意味着a和b现在指向释放的内存,可以随时重新分配,然后可以被完全不相关的数据覆盖。