0

我有

int * array=new int[2];

我想释放最后一个元素的内存,从而将分配的内存减少到只有 1 个元素。我试着打电话

delete array+1;

但它给出了错误

*** 检测到 glibc *** skuska:free():无效指针:0x000000000065a020 *

这可以在没有显式重新分配的情况下在 C++03 中完成吗?

注意:如果我想使用类而不是原始数据类型(如 int),如何释放内存以便也调用类的析构函数?

注2:我正在尝试实施vector::pop_back

4

4 回答 4

5

不要new[]为此使用表达式。这不是矢量的工作方式。你所做的是分配一块原始内存。您可以为此使用 malloc ,也可以使用operator new,这与 new 表达式不同。假设您使用了默认分配器,这基本上就是reserve()成员函数的作用。std::vector它不会像new[]表达式那样创建任何实际对象。

当你想构造一个元素时,你可以使用placement new,将它传递给你分配的原始内存中的某个位置。当你想破坏一个元素时,你直接调用它的析构函数。完成后,不要使用delete[]表达式,而是使用operator deleteif you used operator new,或者使用free()if you used malloc

这是一个创建 10 个对象并以相反顺序销毁它们的示例。我可以按任何顺序销毁它们,但这是你在向量实现中的做法。

int main()
{
    void * storage = malloc(sizeof(MyClass) * 10);

    for (int i=0; i<10; ++i)
    {
        // this is placement new
       new ((MyClass*)storage + i) MyClass;
    }

    for (int i=9; i>=0; --i)
    {
        // calling the destructor directly
        ((MyClass*)storage + i)->~MyClass();
    }

    free(storage);
}

pop_back将通过简单地调用最后一个元素的析构函数并将 size 成员变量减 1 来实现。它不会、不应该(并且不能,如果不制作一堆不必要的副本)释放任何内存。

于 2012-11-04T04:03:08.710 回答
4

没有这样的选择。调整数组大小的唯一方法是分配具有 size 的新数组old_size - 1,复制旧数组的内容,然后删除旧数组。

如果你想要释放对象内存,为什么不创建指针数组呢?

MyClass **arr = new MyClass*[size];
for(int i = 0; i < size; i++)
 arr[i] = new MyClass;

// ...

delete arr[size-1];
于 2012-11-04T03:03:54.167 回答
3

std::vector::pop_back不会重新分配任何东西——它只是更新确定数据大小的内部变量,将其减一。旧的最后一个元素仍然存在于内存中;该向量根本不允许您通过其公共 API 访问它。*

这一点,以及不断增长的重新分配是非线性的,是为什么std::vector::capacity()不等于std::vector::size().

因此,如果您真的出于任何原因尝试重新发明std::vector,那么您关于重新分配的问题的答案是don't


* 实际上,对于非原始数据类型,它稍微复杂一些,因为即使它们的内存不会被释放,这些元素也会在语义上被破坏。

于 2012-11-04T03:49:16.500 回答
0

由于您使用的是 C++03,因此您可以访问std::vector数据类型。使用它,这是一个电话:

#include <vector>
//...
std::vector<int> ary(3);
//...
ary.erase(ary.begin() + (ary.size() - 1));

或者

#include <vector>
//...
std::vector<int> ary(3);
//...
ary.pop_back();

编辑:

你为什么要重新发明轮子?只需使用vector::pop_back。

无论如何,只有当包含的数据类型不是指针时,才会在包含的数据类型上调用析构函数。如果它是指针,则必须手动对要删除的对象调用 delete ,将其设置为nullptror NULL(因为尝试对先前删除的对象调用 delete 是不好的,对空指针调用 delete 是非操作),然后调用擦除。

于 2012-11-04T03:17:23.210 回答