从STL Vector中删除指针 [英] Deleting Pointers from STL Vector

查看:185
本文介绍了从STL Vector中删除指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在迭代一个基类指针向量并删除符合某个标准的那些

...我正在使用漂亮的教科书代码

特定删除/删除(它直接来自迈尔斯'有效

STL),并且如下所示:


无效CGame :: RemoveDeadObjects()

{

//清理人员!!

vector< CDrawableObject *> :: iterator i;


for(i = g_vecGameObjects.begin(); i!=

g_vecGameObjects.end();)

{

//如果对象不为空且可以删除...

if((* i)&&(* i) - > CanRemove())

{

//在删除前抓住

CDrawableObject * toDie = * i;


//擦除...

i = g_vecGameObjects.erase(i);


// ...并杀死

删除toDie;

toDie = NULL;

}

else

++ i;

}

}


这里'问题所在:在两行说删除toDie; toDie =

NULL;我注意到toDie指向的原始变量没有被设置为NULL,只是toDie。
换句话说,如果其中一个CDrawableObjects *被说出来,那么CGame的成员var

名为m_cdPlayer1,当删除/设置为-NULL发生:


1.在删除之前,toDie和m_cdPlayer1的值为

0x00a72498。


2.删除后,toDie和m_cdPlayer1都将__vfptr

指向内存0xFEEEFEEE(表示删除)


3.设置为-null,toDie的值变为0x00000000,而

m_cdPlayer1的值仍为0x00a72498(同时仍指向

0xFEEEFEEE)。


不是我想要的行为。此时,m_cdPlayer1被正式删除,但是测试if(m_cdPlayer)被删除了。失败,因为它在技术上是

而不是NULL。


关于如何获得预期行为的任何建议或建议

out of这个片段?


- Hanzo


[见 http://www.gotw.ca/resources/clcm.htm 有关的信息]

[comp.lang.c ++ .moderated。第一次海报:做到这一点! ]

解决方案

[已删除交叉发布到审核组。我宁愿不等待

审核。一般来说,你不应该交叉发布到经过审核的小组。]


Hanzo写道:

我正在迭代一个基数向量类指针和删除符合某个标准的那些......我正在使用漂亮的文本书代码来进行特定的删除/删除(它直接来自迈尔斯的'有效
STL),读起来像这样:

void CGame :: RemoveDeadObjects()
{
//清理人员!!
vector< CDrawableObject *> ; :: iterator i;

for(i = g_vecGameObjects.begin(); i!=
g_vecGameObjects.end();)
{
//如果object不为null,可以删除...
if((* i)&&(* i) - > CanRemove())
//抓住之前擦除
CDrawableObject * toDie = * i;

//擦除......
i = g_vecGameObjects.erase(i);

// ...并且杀死
删除toDie;
toDie = NULL;


当它即将超出范围并且

不再存在时,为什么还要把它设置为NULL?


另外,这样做也没有错:


delete * i;

i = g_vecGameObjects.erase(i);

}
其他
++我;
}
}

这就是问题所在:在两行上说删除toDie; toDie =
NULL;我注意到toDie指向的原始变量没有设置为NULL,只是toDie。本身。


toDie指向的原始变量消失了。它不存在
。你删除了它。一旦你完成了这个,你没有生意

试图确定它的价值。

换句话说,如果说一个CDrawableObjects *,那就是一个成员var CGame名为m_cdPlayer1,当删除/设置为NULL时:


你说你有两个不同的,无关的指针指向

是同一个动态创建的对象?在这种情况下,你的问题很糟糕

设计。解决方法是修复设计。

1.删除前,toDie和m_cdPlayer1的值为0x00a72498。

2.删除后,两者都有toDie和m_cdPlayer1有__vfptr
指向内存0xFEEEFEEE(表示删除)


我不知道__vfptr是什么,但指针只是指针 - 他们

不要拥有任何叫做__vfptr的东西。从理论上讲,他们可以指出那些确实存在的东西,但在这种情况下你已经删除了他们指向b
的东西,所以你可能不会检查它或试图确定它价值

无论如何。如果这样做,你的程序的行为是不确定的。

3.设置为null后,toDie的值变为0x00000000,而
m_cdPlayer1保持值为0x00a72498(同时仍然指向
0xFEEEFEEE)。


当然。

不是我想要的行为。此时,m_cdPlayer1被正式删除,但测试if(m_cdPlayer)被删除。失败,因为它在技术上不是NULL。


当然。

关于如何从这个片段中获取预期行为的任何建议或建议?



不要在两个指针之间共享一个对象。或者,如果你这样做,

有一个指针拥有对象 - 永远不要试图通过

删除它的另一个指针。但这可能会变得复杂。你必须确定

主人没有删除它,而它仍然可以通过任何

其他指针访问。


一般情况下,您无法知道指针

指向的对象是否仍然存在,或者是否已被删除,以及任何尝试引用已删除的

对象的原因未定义的行为。


-Kevin

-

我的电子邮件地址有效,但会定期更改。

要与我联系,请使用最近发布的地址。


" Hanzo" <公顷*** @ milclan.com>在留言中写道

新闻:om ******************************** @ 4ax.com ...
http://www.cuj.com/documents/s=8890/...p0310alexandr/

[...]
关于如何从这个片段中获得预期行为的任何建议或建议?




是的。使用智能指针。然后,只需销毁你不再需要的指针副本。当对象的最后一个指针被销毁时,

将释放该对象。这是一个非常流行的智能指针:

www.boost.org/libs/smart_ptr/index.htm


Dave


---

外发邮件已通过无病毒验证。

由AVG反病毒系统检查( http://www.grisoft.com)

版本:6.0.521 /病毒库:319 - 发布日期:2003年9月23日


>我正在迭代一个基类指针向量并删除符合某个标准的

...我正在使用漂亮的教科书代码来确定特定的删除/擦除(它直接来自迈尔斯的'有效
STL),并且如下所示:

void CGame :: RemoveDeadObjects()
{
/ / cleanup crew !!
vector< CDrawableObject *> :: iterator i;

for(i = g_vecGameObjects.begin(); i!=
g_vecGameObjects.end() ;)
{
//如果对象不为空并且可以删除...
if((* i)&&(* i) - > CanRemove())
{删除之前抓住
CDrawableObject * toDie = * i;

//擦除...
i = g_vecGameObjects.erase( i);

// ...并且杀了
删除toDie;
toDie = NULL;
}

++ i;
}
}

这里''问题所在:在两行上说删除toDie; toDie =
NULL;


在那些线条到达范围之后;为什么还要把它设置为

NULL?

我注意到toDie指向的原始变量没有设置为NULL,只是toDie ;本身。




''toDie = NULL;''只将toDie指针设置为NULL,它不会影响

它指向的对象至。请注意,该对象不再存在于

,因为它被设置为NULL,因为它在

之前被删除了。


-

Peter van Merkerk

peter.van.merkerk(at)dse.nl


[见< a rel =nofollowhref =http://www.gotw.ca/resources/clcm.htmtarget =_ blank> http://www.gotw.ca/resources/clcm.htm 有关的信息]

[comp.lang.c ++。moderated。第一次海报:做到这一点! ]


I''m iterating over a vector of base class pointers and deleting those
which meet a certain criteria...i''m using pretty text-book code for
the particular delete/erasure (it''s straight out of Myers'' Effective
STL), and reads like this:

void CGame::RemoveDeadObjects()
{
// cleanup crew!!
vector<CDrawableObject*>::iterator i;

for (i = g_vecGameObjects.begin(); i !=
g_vecGameObjects.end();)
{
// if object is not null and can be removed...
if ((*i) && (*i)->CanRemove())
{
// grab hold before erasure
CDrawableObject* toDie = *i;

// erase...
i = g_vecGameObjects.erase(i);

// ...and kill
delete toDie;
toDie = NULL;
}
else
++i;
}
}

Here''s the problem: on the two lines that say delete toDie; toDie =
NULL; I am noticing that the original variable to which toDie is
pointing is not being set to NULL, just "toDie" itself.

In other words, if one of the CDrawableObjects* was say, a member var
of CGame called m_cdPlayer1, when the delete/set-to-NULL happens:

1. Before the delete, toDie and m_cdPlayer1 have a value of
0x00a72498.

2. After the delete, both toDie and m_cdPlayer1 have their __vfptr
point to memory 0xFEEEFEEE (signifying a delete)

3. After the set-to-null, the value of toDie becomes 0x00000000, while
m_cdPlayer1 remains at a value of 0x00a72498 (while still pointing to
0xFEEEFEEE).

Not the behavior I want. At this point, m_cdPlayer1 is officially
deleted, yet the test "if (m_cdPlayer)" fails, since it is technically
not NULL.

Any suggestions or recommendations on how to get the intended behavior
out of this snippet?

- Hanzo

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

解决方案

[Cross-post to moderated group removed. I''d rather not wait for
moderation. Generally, you should not cross-post to moderated groups.]

Hanzo wrote:

I''m iterating over a vector of base class pointers and deleting those
which meet a certain criteria...i''m using pretty text-book code for
the particular delete/erasure (it''s straight out of Myers'' Effective
STL), and reads like this:

void CGame::RemoveDeadObjects()
{
// cleanup crew!!
vector<CDrawableObject*>::iterator i;

for (i = g_vecGameObjects.begin(); i !=
g_vecGameObjects.end();)
{
// if object is not null and can be removed...
if ((*i) && (*i)->CanRemove())
{
// grab hold before erasure
CDrawableObject* toDie = *i;

// erase...
i = g_vecGameObjects.erase(i);

// ...and kill
delete toDie;
toDie = NULL;
Why bother setting this to NULL when it''s about to go out of scope and
cease to exist?

Also, there would be nothing wrong with doing this instead:

delete *i;
i = g_vecGameObjects.erase(i);
}
else
++i;
}
}

Here''s the problem: on the two lines that say delete toDie; toDie =
NULL; I am noticing that the original variable to which toDie is
pointing is not being set to NULL, just "toDie" itself.
The original variable to which toDie was pointing is gone. It doesn''t
exist. You deleted it. Once you''ve done that, you have no business
attempting to determine its value.

In other words, if one of the CDrawableObjects* was say, a member var
of CGame called m_cdPlayer1, when the delete/set-to-NULL happens:
You are saying you have two different, unrelated pointers pointing to
the same dynamically created object? In that case, your problem is poor
design. The solution is to fix the design.

1. Before the delete, toDie and m_cdPlayer1 have a value of
0x00a72498.

2. After the delete, both toDie and m_cdPlayer1 have their __vfptr
point to memory 0xFEEEFEEE (signifying a delete)
I don''t know what a __vfptr is, but pointers are just pointer - they
don''t "have" anything called __vfptr. Theoretically, they could point to
something that does, but in this case you have deleted the thing they
point to, so you may not examine it or attempt to determine its value in
any way. If you do so, your program''s behavior is undefined.

3. After the set-to-null, the value of toDie becomes 0x00000000, while
m_cdPlayer1 remains at a value of 0x00a72498 (while still pointing to
0xFEEEFEEE).
Of course.

Not the behavior I want. At this point, m_cdPlayer1 is officially
deleted, yet the test "if (m_cdPlayer)" fails, since it is technically
not NULL.
Of course.

Any suggestions or recommendations on how to get the intended behavior
out of this snippet?



Don''t share an object between two pointers like that. Or, if you do,
have one pointer "own" the object - never attempt to delete it through
the other pointer. This can get complicated, though. You have to be sure
the owner doesn''t delete it while it may still be accessed through any
other pointer.

In general, you cannot know whether the object pointed to by a pointer
still exists, or has been deleted, and any attempt to refer to a deleted
object causes undefined behavior.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.


"Hanzo" <ha***@milclan.com> wrote in message
news:om********************************@4ax.com...
http://www.cuj.com/documents/s=8890/...p0310alexandr/

[...]
Any suggestions or recommendations on how to get the intended behavior
out of this snippet?



Yes. Use a smart pointer. Then, just destroy the copies of pointers that
you don''t want any more. When the last pointer to the object is destroyed,
the object will be freed. Here''s a pretty popular smart pointer:

www.boost.org/libs/smart_ptr/index.htm

Dave

---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.521 / Virus Database: 319 - Release Date: 9/23/2003


> I''m iterating over a vector of base class pointers and deleting those

which meet a certain criteria...i''m using pretty text-book code for
the particular delete/erasure (it''s straight out of Myers'' Effective
STL), and reads like this:

void CGame::RemoveDeadObjects()
{
// cleanup crew!!
vector<CDrawableObject*>::iterator i;

for (i = g_vecGameObjects.begin(); i !=
g_vecGameObjects.end();)
{
// if object is not null and can be removed...
if ((*i) && (*i)->CanRemove())
{
// grab hold before erasure
CDrawableObject* toDie = *i;

// erase...
i = g_vecGameObjects.erase(i);

// ...and kill
delete toDie;
toDie = NULL;
}
else
++i;
}
}

Here''s the problem: on the two lines that say delete toDie; toDie =
NULL;
After those lines toDie runs out of scope; why bother setting it to
NULL?
I am noticing that the original variable to which toDie is
pointing is not being set to NULL, just "toDie" itself.



''toDie = NULL;'' only sets the toDie pointer to NULL it does not affect
the object it was pointing to. Note that that object no longer exists at
the point toDie is being set to NULL because it was deleted just before
that line.

--
Peter van Merkerk
peter.van.merkerk(at)dse.nl

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


这篇关于从STL Vector中删除指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆