结构体数组和new/delete

7

我有一个这样的结构体:

class Items 
{
private:
    struct item
    {
        unsigned int a, b, c;
    };
    item* items[MAX_ITEMS];
}

假设我想要“删除”一个项目,像这样:

items[5] = NULL;

后来我在同一位置创建了一个新项目:


items[5] = new item;

我是否需要调用delete[]来清理这个数组?或者在编译之前已知数组items[]的范围,因此不需要这样做?

将指针设置为NULL是有效的吗?还是我应该在那里调用delete?

8个回答

16

在将指针设置为NULL之前,您需要调用delete。(将其设置为NULL不是必需的,但如果您在删除指针后意外尝试取消引用,则可以帮助减少错误。)

请记住,每次使用new时,您都需要在同一指针上稍后使用delete。永远不要单独使用其中一个。

此外,new []delete []以相同的方式配对,但您永远不应将new []deletenewdelete []混合使用。在您的示例中,由于您使用new(而不是创建对象数组的new []),因此您必须使用delete(而不是delete [])删除该对象。


6
正如Kluge所指出的那样,你会像这样泄漏索引5处的对象。但是这个问题听起来更像是你不应该手动操作,而是在Item内部使用一个容器类。如果你实际上不需要将这些item对象存储为指针,请使用std::vector<item>代替那个包含MAX_ITEMS指针的数组。如果需要,你也可以在中间插入或删除向量元素。
如果需要将对象存储为指针(通常情况下,如果结构体item实际上是多态的,与你的示例不同),则可以使用Boost.PtrContainer中的boost::ptr_vector<item>。
示例:
class Items {
private:
    struct item {
        unsigned int a, b, c;
    };
    std::vector<item> items;
}

if (items.size() > 5) // (just to ensure there is an element at that position)
    items.erase(items.begin() + 5); // no need to use operator delete at all

1

删除一个项目使用:

delete items[5];

删除项目后,建议将删除的指针设置为NULL,这样如果您以后错误地再次删除它,就不会出现错误。

items [5] = NULL


1

只是为了明确起见:您指的是调用“delete[]”。我想您的意思是 delete

我提到这一点是因为C++有两个不同的运算符,operator deleteoperator delete[]。后者用于删除使用operator new[]分配的对象数组,并且在此情况下不适用。您有一个指向对象的指针数组,必须使用重复调用operator new而不是单个调用operator new[]来初始化它。

我真正想说的是:您对delete[]的使用令人困惑和模棱两可;请将其更改为delete


1

这里有几个相关的问题:

  1. 根据你发布的代码,数组本身没有在堆上分配(除非是结构体),因此你不需要delete[]数组。如果你使用new[]创建了该数组,则必须使用delete[]来删除它。
  2. 发布的代码没有说明从数组指向的对象如何分配内存。 如果您在堆栈上分配这些对象,则不能删除它们(然而,当指向的对象超出范围时,您的指针将无效)。 如果您在堆上分配它们(使用new),则在对象超出范围时必须删除它们。
  3. 正如其他人已经建议的那样,如果您使用容器-特别是STL容器-和智能指针,情况会变得更加简单。目前智能指针意味着使用Boost指针。

1
假设我想要“删除”一个项目,就像这样:
items[5] = NULL;
我对Visual Basic了解不多,但这似乎是一种Visual Basic编程习惯用法,因为“Set a = None”(或Null,我不确定)会删除a指向的对象(或者减少其引用计数,对于COM对象)。

正如其他人提到的,你应该使用以下任意一种:

delete items[5];
items[5] = newContent;

或者:

delete items[5];
items[5] = NULL;

delete[5]之后,存储在items[5]中的指针唯一可能的用途是给你带来麻烦。更糟糕的是,它可能在开始时运行良好,只有当你在先前由*items[5]使用的空间上分配其他内容时才会失败。这些是使C/C++编程“有趣”的原因,即真正令人讨厌(即使像我这样喜欢C的人也是如此)。

只写delete items[5];可以节省无用的写入,但这是一种过早的优化。


0

C++不是我的强项,但我非常确定如果你将指针设置为NULL,你会泄漏内存。

编辑:泄漏的内存将是数组中指针所指向的内存。


0

将items[5]设置为NULL并不会删除与该项关联的内存,它只是将指向该项的指针设置为NULL,因此内存泄漏。

您可以通过调用以下方法来删除该项:

delete items[5];

由于 C++ 没有自动垃圾回收机制,您需要删除任何不再需要的内存。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接