这是缩小数组的有效方法吗?

Is this a valid way to shrink an array?

本文关键字:方法 有效 缩小 数组      更新时间:2023-10-16

我想获取一个大小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;
}
    b = a;
    delete[] a;

在此之后使用 ba 是 UB,因为b指向与 a 相同的数组/位置。它们在分配后表示相同的数组。因此,当您删除数组两次时,delete[] b;也是 UB。

不,你泄露了最初分配给 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 如何处理矢量,其中调整大小到较小的大小将减小大小,但容量保持不变。

不,正如其他地方提到的,这段代码是错误的,实际上这些操作(new,delete)的组合可以在不复制数据的情况下实现您的目的。

有一个函数 realloc() 可以完全按照你想要的去做,但你应该只在用 malloc() 分配的内存上使用它。

矢量等标准库函数具有重新分配的能力。这是执行您所描述操作的首选方法。

不,你所做的是未定义的行为。

首先,您在double* b = new double[M];行中分配的数组将永远不会被释放,因为您在下一行中重新分配了指向该内存的唯一指针。(b = a;)。这是一个经典的内存泄漏。

其次,在下一行delete [] a;删除ab都指向的数组。这意味着 a 和 b 现在都指向释放的内存,该内存可以随时重新分配,然后可以被完全不相关的数据覆盖。