我有一些代码使用了大量指向同一地址的指针。 给出一个相同的简单示例:
int *p = new int(1);
int *q = p;
int *r = q;
delete r; r = NULL; // ok
// delete q; q = NULL; // NOT ok
// delete p; p = NULL; // NOT ok
如何在没有多次删除的情况下安全地删除它? 如果我有很多指针都指向同一地址的对象,那么这一点尤其困难。
答案 0 :(得分:28)
您的工具是shared_ptr
库的boost
。请查看文档:{{3}}
示例:
void func() {
boost::shared_ptr<int> p(new int(10));
boost::shared_ptr<int> q(p);
boost::shared_ptr<int> r(q);
// will be destructed correctly when they go out of scope.
}
答案 1 :(得分:18)
答案是,不使用托管指针,你应该知道是否根据分配的位置删除指针。
您的示例有点人为,但在实际应用程序中,负责分配内存的对象将负责销毁它。接收已经初始化的指针并将它们存储一段时间的方法和函数不会删除那些指针;这个责任在于最初分配内存的任何对象。
请记住,拨打new
的电话应该通过拨打delete
来平衡。每次分配内存时,知道你必须编写平衡代码(通常是析构函数)来释放内存。
答案 2 :(得分:10)
“现代”的答案是使用智能指针,不要进行任何手动删除。
boost::shared_ptr<int> p(new int(1));
boost::shared_ptr<int> q = p;
boost::shared_ptr<int> r = q;
故事结束!
答案 3 :(得分:3)
您面临的问题是程序中的所有权语义不明确。从设计的角度来看,尝试确定每个步骤中对象的所有者。在许多情况下,这意味着创建对象的人将不得不在以后删除它,但在其他情况下,所有权可以转移甚至共享。
一旦你知道谁拥有内存,那么回到代码并实现它。如果一个对象是唯一负责不同对象的对象,那么它应该通过单一所有权智能指针(std::auto_ptr
/ unique_ptr
)或者甚至是一个原始指针来保存它(尽量避免这样做)常见的错误来源)并手动管理内存。然后将引用或指针传递给其他对象。转移所有权后,使用智能指针工具将对象提供给新所有者。如果所有权是真正共享的(没有明确的已分配对象的所有者),那么您可以使用shared_ptr
并让智能指针处理内存管理。)
答案 4 :(得分:1)
你为什么试图任意删除指针?每个动态分配的对象都由一个所有者在一个位置分配。并且应该由一个所有者负责确保再次删除该对象。
在某些情况下,您可能希望将所有权转移到其他对象或组件,在这种情况下,删除的责任也会发生变化。
有时,您只是想忘记所有权并使用共享所有权:使用该对象的所有人共享所有者,并且只要至少有一个用户存在,就不应删除该对象。
然后使用shared_ptr
。
简而言之,使用RAII。不要尝试手动删除对象。
答案 5 :(得分:0)
在某些非常罕见的情况下,您可能无法使用智能指针(可能处理旧代码),但也无法使用简单的“所有权”方案。
想象一下,你有一个std::vector<whatever*>
,并且一些whatever*
指针指向同一个对象。安全清理涉及确保不要删除相同的两次 - 所以建立一个std::set<whatever*>
,只删除集合中尚未存在的指针。删除所有指向的对象后,也可以安全地删除这两个容器。
insert
的返回值可用于确定插入的项目是否为新项目。我没有测试过以下(或者使用std :: set一段时间),但我认为以下是正确的......
if (myset.insert (pointervalue).second)
{
// Value was successfully inserted as a new item
delete pointervalue;
}
当然,您不应该设计项目以使其成为必要,但如果您无法避免,那么处理这种情况并不难。
答案 6 :(得分:0)
无法知道指针引用的内存是否已被删除,如您的情况 如果您不能使用具有智能指针的库,那些引用计数,并且您无法实现自己的引用计数模式(如果确实需要执行您在帖子中描述的操作),请尝试在指针上调用realloc。 /> 我在其他帖子中读到,根据实现,对realloc的调用可能不会崩溃但返回空指针。在这种情况下,您知道该指针引用的内存已被释放 如果这是一个肮脏的解决方案,它将无法移植,但如果您没有其他选择,请尝试它。更糟糕的当然是崩溃你的应用程序:)
答案 7 :(得分:0)
我想说有时候,智能指针实际上可以减慢你的应用程序,而不是很多。我要做的是创建一个方法,如下所示:
void safeDelete(void **ptr)
{
if(*ptr != NULL)
{
delete ptr;
*ptr = NULL;
}
}
我不确定我是否100%正确地完成了它,但你做的是你将指针传递给这个带有指针指针的方法,检查以确保它指向的指针没有设置为NULL,然后删除该对象,然后将地址设置为0或NULL。纠正我,如果这不是一个很好的方法,我也是新手,有人告诉我这是一个很好的检查方式,而不会变得复杂。