如何释放作为更大数组一部分的子数组的内存

Posted

技术标签:

【中文标题】如何释放作为更大数组一部分的子数组的内存【英文标题】:How to free subarray's mem which is part of bigger array 【发布时间】:2017-08-08 11:14:27 【问题描述】:

我在动态内存删除方面遇到了一些问题。我有 100 个整数的数组,但稍后在运行时没有使用超过一半的数组,所以我想释放该内存。这是我的尝试。谁能解释我为什么会出错?谢谢!

void dynSybarrDel()
    int* intArr = new int[100];
    int* subArr = (intArr + 50);
    delete subArr;

【问题讨论】:

这是不可能的。你必须 delete[]new[] (你不使用 delete[] 所以你有 两个 错误)。您尝试以这种方式解决的实际问题是什么?为什么要“释放子数组”? 我有一个代表库存的类,并且每时每刻都会删除很多项目,但添加的项目并不多,所以我想优化内存使用。感谢您的回答! 所以你需要一个container 可以扩展一些,但主要是缩小?从“默认”容器std::vector 开始,看看这是否足以满足您的需求。您可以根据需要单独更改其大小(向量中的元素数)和容量(分配的内存)。然后我建议您简单地忘记 以优化空间,除非您的目标是有限的系统。优化空间或性能应该是您最后做的事情。只有当你真的需要它时。 【参考方案1】:

但是如果你 malloc 内存,你可以用 realloc 删除到最后:

#include  <cstring>
void dynSybarrDel()
    int* intArr = (int*)malloc(100 * sizeof(int));
    int* subArr = (intArr + 50);
    intArr = realloc(intArr, (subArr - intArr)*sizeof(int));
;

编辑

要在mallocated 内存中初始化特定类型的数组元素,只需执行此操作(但是,当您知道它在读取之前被覆盖时,您不需要在 int 或其他内置类型上执行此操作,否则会有随机值):

new(elementPtr) myType("parameter1", 2.0);

然后销毁:

elementPtr->~myType();

elementPtr 只是一个元素的地址,如下所示:

MyType* elementPtr = myArr;
for(int i = arrSize; i; --i, ++elementPtr)

但是,如果您可以使用std::vector,它可以让您做更多事情:

#include <vector>

void dynSybarrDel()
    std::vector<int> intArr(100);
    auto subArr = intArr.begin() + 50;
    intArr.erase(subArr, intArr.end());
;

您甚至可以删除向量内的一部分:

#include <vector>
#include <numeric>

int main() 
    std::vector<int> intArr(10);
    std::iota(intArr.begin(), intArr.end(), 0); // linear counting [0, 10)

    for(int i: intArr) 
        std::cout << i << ' ';
    ;
    std::cout << '\n';
    
    auto eraseMeBegin = intArr.begin() + 3;
    auto eraseMeEnd   = intArr.end() - 2;

    intArr.erase(eraseMeBegin, eraseMeEnd);

    for(int i: intArr) 
        std::cout << i << ' ';
    ;
    std::cout << '\n';
;

产生的输出:

0 1 2 3 4 5 6 7 8 9

0 1 2 8 9

【讨论】:

谢谢!这就是我要找的东西! realloc 对非平凡类型很危险,因为它可能会将数据复制到新缓冲区中。此外,(int)subArr - (int)intArr 是一种不安全的计算缓冲区大小的方法。 只需要正则减法即可;反正没必要先转成ints。 一些 stl 实现只是在它们的迭代器中使用指针,其他的包括对容器的引用和偏移量(较慢),如果你把它放在一个结构中或者只是做操作都没有关系直接地。如果 stl 用户失败,正确使用类型,这将始终是一个安全问题。 @DanielH:常规减法还不够,因为结果会丢失元素大小的一个因素。【参考方案2】:

这里的代码:int* intArr = new int[100]; 告诉编译器提供 4*100 的内存空间。你基本上把它分配给你自己使用——在它回到内存池之前,没有人可以在你的程序旁边使用它。

因为编译器已经按照你告诉他的做了(并且给了你内存)。您不能要求他在运行时忽略它。 但是,您可以请求一半的空间并稍后在您的程序中分配新的内存。

在重新分配新内存时,编译器首先会尝试查看当前内存的扩展是否空闲并且大小是否适合您。如果是这样,它会为您提供当前数组的延续地址,如果不是,它会将您当前的数组复制到另一个具有足够空间的内存地址(如果可能)。

【讨论】:

以上是关于如何释放作为更大数组一部分的子数组的内存的主要内容,如果未能解决你的问题,请参考以下文章

在python中创建没有作为参数传递的aubarrays的子数组

如何填充作为另一个文档的数组元素的子文档的字段?

如何释放动态结构数组的内存

算法 | 归并排序

如何在 C# 中搜索字符串数组中的子字符串

ClickHouse 截取数组的部分元素,得到一个新的子数组: arraySlice (array, offset[, length])...