C++ 结构数组和新/删除
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/434140/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Array of structs and new / delete
提问by Daniel Sloof
I have a struct like this:
我有一个这样的结构:
class Items
{
private:
struct item
{
unsigned int a, b, c;
};
item* items[MAX_ITEMS];
}
Say I wanted to 'delete' an item, like so:
假设我想“删除”一个项目,如下所示:
items[5] = NULL;
And I created a new item on that same spot later:
后来我在同一个地方创建了一个新项目:
items[5] = new item;
Would I still need to call delete[]
to clean this up? Or won't this be needed since bounds of array items[]
are known before compiling?
我还需要打电话delete[]
来清理吗?还是不需要这样做,因为items[]
在编译之前就知道数组的边界?
Is setting that pointer to NULL valid or should I be calling delete there?
将该指针设置为 NULL 有效还是应该在那里调用 delete?
回答by Jeremy Ruten
You need to call delete
before setting it to NULL. (Setting it to NULL isn't required, it just helps reduce bugs if you accidentally try to dereference the pointer after deleting it.)
您需要delete
在将其设置为 NULL 之前调用。(不需要将其设置为 NULL,如果您在删除指针后不小心尝试取消引用它,它只会有助于减少错误。)
Remember that every time you use new
, you will need to use delete
later on the same pointer. Never use one without the other.
请记住,每次使用 时new
,您都需要delete
稍后在同一个指针上使用。永远不要在没有另一个的情况下使用一个。
Also, new []
and delete []
go together in the same way, but you should never mix new []
with delete
or new
with delete []
. In your example, since you created the object with new
(rather than new []
which would create an array of objects) you must delete the object with delete
(rather than delete []
).
此外,new []
并delete []
以相同的方式一起使用,但您不应该new []
与delete
或混合new
使用delete []
。在您的示例中,由于您使用new
(而不是new []
创建对象数组)创建了对象,因此您必须使用delete
(而不是delete []
)删除对象。
回答by Pyry Jahkola
As Kluge pointed out, you'd leak the object at index 5 like that. But this one really sounds like you shouldn't do this manually but use a container class inside Item
. If you don't actually need to store these item
objects as pointers, use std::vector<item>
instead of that array of MAX_ITEMS
pointers. You can always insert or erase vector elements in the middle as well if you need to.
正如克鲁格指出的那样,你会像那样泄漏索引 5 处的对象。但这听起来确实像是您不应该手动执行此操作,而是在Item
. 如果您实际上不需要将这些item
对象存储为指针,请使用std::vector<item>
该MAX_ITEMS
指针数组代替。如果需要,您也可以随时在中间插入或删除矢量元素。
In case you need to store the objects as pointers (usually if struct item
is actually polymorphic, unlike in your example), you can use boost::ptr_vector<item> from Boost.PtrContainerinstead.
如果您需要将对象存储为指针(通常如果 structitem
实际上是多态的,与您的示例不同),您可以使用Boost.PtrContainer 中的boost::ptr_vector<item>代替。
Example:
例子:
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
回答by Joao Vilaca
To delete an item use:
要删除项目,请使用:
delete items[5];
删除项目[5];
after deleting the item it is advisable to set the deleted pointer to NULL, so you won't have an error if you later delete it again by mistake.
删除项目后,建议将删除的指针设置为 NULL,这样以后再误删除就不会出错。
items[5] = NULL
项目[5] = NULL
回答by Blaisorblade
Say I wanted to 'delete' an item, like so:
items[5] = NULL;
假设我想“删除”一个项目,如下所示:
项目[5] = NULL;
I know little Visual Basic, but that smells like a Visual Basic programming idiom, since "Set a = None" (or Null, I'm not sure) would delete the object pointed by a (or rather decrement its reference count, for COM objects).
我对 Visual Basic 知之甚少,但这闻起来像一个 Visual Basic 编程习语,因为“Set a = None”(或 Null,我不确定)会删除 a 指向的对象(或者更确切地说是减少其引用计数,对于 COM对象)。
As somebody else noted, you should use either:
正如其他人指出的那样,您应该使用:
delete items[5];
items[5] = newContent;
or:
或者:
delete items[5];
items[5] = NULL;
After delete[5]
, the only possible use of the pointer stored in items[5]
is causing you trouble. What's worse is that it might happen to work at the beginning, and start failing only when you allocate something else over the space previously used by *items[5]
. Those are the causes which make C/C++ programming "interesting", i.e. really annoying (even for who likes C like me).
之后delete[5]
,唯一可能使用存储在中的指针items[5]
会给您带来麻烦。更糟糕的是,它可能刚开始工作,只有当您在*items[5]
. 这些是使 C/C++ 编程“有趣”的原因,即真的很烦人(即使对于像我这样喜欢 C 的人)。
Writing just delete items[5];
saves what can be an useless write, but that's a premature optimization.
写入只是delete items[5];
保存了无用的写入,但这是过早的优化。
回答by j_random_hacker
Just to be clear: you refer to calling "delete[]
". I think you mean delete
.
只是要清楚:您指的是调用“ delete[]
”。我想你的意思是delete
。
I mention this because C++ has two separate operators, operator delete
and operator delete[]
. The latter is used for deleting arrays of objects allocated with operator new[]
, and does notapply in this case. You have an array of pointers toobjects, which you must have initialised with repeated calls to operator new
rather than a single call to operator new[]
.
我提到这一点是因为 C++ 有两个独立的运算符,operator delete
和operator delete[]
. 后者用于删除与分配对象的阵列operator new[]
,并且不会不适用于这种情况。你有一个指向对象的指针数组,你必须用重复调用operator new
而不是单个调用来初始化它们operator new[]
。
All I'm really trying to say is: your use of delete[]
is confusing and ambiguous; change it to delete
.
我真正想说的是:你的使用delete[]
令人困惑和模棱两可;将其更改为delete
.
回答by Max Lybbert
There are a few, related, questions here:
这里有一些相关的问题:
- According to the code you posted, the array itself is not allocated on the heap unless the
struct
is, so you don't need todelete[]
the array. If you created the array withnew[]
you would have todelete[]
it. - The code posted doesn't say how the objects being pointed to from the array are allocated. If you allocate those objects on the stack you must notdelete them (then again, this is highly unlikely because your pointers will become invalid when the objects they point to fall out of scope). If you allocated them on the heap (with new) then you mustdelete them when they fall out of scope.
- As others have already suggested, life is much easier if you use a container -- especially an STL container -- and smart pointers -- which for now means pointers out of Boost.
- 根据您发布的代码,除非
struct
是,否则数组本身不会在堆上分配,因此您不需要delete[]
数组。如果您使用它创建了数组,则new[]
必须使用delete[]
它。 - 发布的代码没有说明如何分配从数组中指向的对象。如果您在堆栈上分配这些对象,则不得删除它们(同样,这不太可能,因为当它们指向的对象超出范围时,您的指针将变得无效)。如果您将它们分配在堆上(使用 new),那么您必须在它们超出范围时将其删除。
- 正如其他人已经建议的那样,如果您使用容器(尤其是 STL 容器)和智能指针(目前这意味着 Boost 之外的指针),生活会容易得多。
回答by Hank Gay
C++ isn't my strong suit, but I'm pretty sure you'd be leaking the memory if you set the pointer to NULL
.
C++ 不是我的强项,但我很确定如果将指针设置为NULL
.
EDIT: The memory being leaked would be the memory being pointed to by the pointer in the array.
编辑:泄漏的内存将是数组中的指针指向的内存。
回答by Kluge
Setting items[5] to NULL doesn't delete the memory associated with the item, it simply sets the pointer to that item to NULL, therefore the memory is leaked.
将 items[5] 设置为 NULL 不会删除与该项目关联的内存,它只是将指向该项目的指针设置为 NULL,因此内存泄漏。
You can delete the item by calling:
您可以通过调用删除该项目:
delete items[5];
Since C++ has not automatic garbage collection, you need to delete any memory you no longer need.
由于 C++ 没有自动垃圾回收,因此您需要删除不再需要的任何内存。