【问题标题】:Is there a way to free only a part of the dynamically allocated array in C\C++ (shrink existing array)?有没有办法只释放 C\C++ 中动态分配的数组的一部分(缩小现有数组)?
【发布时间】:2016-05-30 04:58:36
【问题描述】:

在一个程序中,我分配了一个巨大的多维数组,进行了一些数字运算,然后只对该数组的第一部分感兴趣,我想只释放数组的一部分并继续使用第一部分的数据。我尝试使用 realloc,但我不确定这是否是正确的方法,因为我必须保留数组中的数据,并且最好避免在内存中复制该块。

#include <cstring>
#include <cassert>
#include <iostream>

using namespace std;

void FillArrayThenTruncate(char* my_array, const int old_size, int* new_size);

int main() {
    const int initial_size = 1024*1024*1024;
    char* my_array = static_cast<char*>(malloc(initial_size));
    assert(my_array);
    int new_size;
    FillArrayThenTruncate(my_array, initial_size, &new_size);
    for(int i = 0; i < new_size; ++i) cout << static_cast<int>(my_array[i]) << endl;
}

void FillArrayThenTruncate(char* my_array, const int old_size, int* new_size) {
    //do something with my_array:
    memset(my_array, 0, old_size);
    for(int i = 0; i < 10; ++i) my_array[i] = i % 3;
    //cut the initial array
    *new_size = 10;
    void* new_array = realloc(my_array, *new_size);
    cout << "Old array pointer: " << static_cast<void*>(my_array) << endl;
    cout << "New array pointer: " << new_array << endl;
    my_array = static_cast<char*>(new_array);
    assert(my_array != NULL);
}

更新:
* 请不要费心建议使用 STL。问题是关于 C 数组的。
* 感谢“R Samuel Klatchko”指出上述代码中的错误。

【问题讨论】:

    标签: c++ memory-management


    【解决方案1】:

    我假设您正在使用它来学习...否则我建议您查看 std::vector 和其他 STL 容器。

    标题问题的答案是否定的。您必须压缩现有元素,或者需要分配新空间并复制所需的数据。 realloc 要么从末端扩展/收缩,要么分配新空间并复制现有数据。

    如果您正在处理如此庞大的数据集,那么您最好只拥有一个块集合,而不是一个单一的集合。如果您只需要某些部分,也许可以避免将整个东西加载到 ram 中。

    【讨论】:

    • +1 用于建议块的集合。如果您可以提前知道要保留多少,这将特别有用。然后,你可以有两个块,当你用完后把下半部分扔掉。您在访问单个元素时会付出轻微的代价,以保证以后没有多余的分配/移动。
    【解决方案2】:

    对于 C++,使用 STL 容器而不是手动处理内存。对于 C,有realloc()

    【讨论】:

    • 鉴于他寻求帮助的具体问题,标准库中的任何内容都不会真正提供开箱即用的帮助。向量不会缩小,只会增长。
    • 有一个简单的成语可以用来轻松收缩向量。 stackoverflow.com/questions/586634/shrinking-a-vector/…我同意这个答案。没有理由在 C++ 中使用 realloc。使用向量。
    • @Dragontamer5788,如果我错了,请纠正我,但在最好的情况下不会重新分配成语和“shrink_to_fit”吗? (即将所有元素复制到新位置)。
    • @alfC 哇,7 年的评论又回来咬我了,嗯?无论如何,我的理解(今天,在我写上述评论 7 年后......)......是 std::swap 可能不会缩小向量。我希望 std::swap 只是交换向量的内部指针。我必须对此进行测试才能确定......
    【解决方案3】:

    是的,如果你用malloc分配,你可以用realloc调整大小。

    也就是说,realloc 可以移动你的记忆,所以你应该为此做好准备:

    // Only valid when shrinking memory
    my_array = realloc(my_array, *new_size);
    

    请注意,如果您正在增加内存,则上述 sn-p 是危险的,因为 realloc 可能会失败并返回 NULL,在这种情况下您将丢失指向 my_array 的原始指针。但是对于缩小内存,它应该始终有效。

    【讨论】:

    • 感谢您的更正——我太不专心地阅读了功能描述并认为 realloc 会修改 my_array,而它恰好返回一个新值。
    • 一般来说,这会尝试将my_array 保持在同一位置吗?
    猜你喜欢
    • 2011-04-15
    • 2011-11-21
    • 1970-01-01
    • 2010-12-05
    • 2018-09-01
    • 2013-06-27
    • 2017-12-13
    • 2014-02-23
    相关资源
    最近更新 更多