假设:
struct Foo
{
Obj* pObj;
Foo() : pObj(NULL);
};
Obj* CreateObj()
{
//do some stuff and then
return new Obj; //obj is a class
}
int main()
{
Foo foo;
foo.pObj = CreateObj();
DoSomeOperationWithTheObj( foo.pObj );
//suppose foo is a monster that should be 'killed' or deleted now
delete foo.pObj;
foo.pObj = NULL;
//the question is can this pointer be 're-used' now like this:
foo.pObj = CreateObj(); //create another object
}
既然指针被删除了,重新使用是不是有问题呢?
至于你原来的问题:是的,你可以重新分配给这样的指针。指针仅保存内存地址,仅此而已。
但是你实际上不应该这样做,因为像这样处理原始指针可能会导致错误,你的代码中已经有一些错误了。现代 C++ 允许您以更好且无需担心的方式执行此操作。假设我们从这段(可编译的)代码开始,我将 Obj 替换为 int,但它是本机类型而不是类这一事实并不重要:
#include <iostream>
struct Foo
{
int* pObj;
Foo() : pObj(NULL) {}
};
int* CreateObj()
{
return new int(42); //obj is a class
}
int main()
{
Foo foo;
foo.pObj = CreateObj();
std::cout << *foo.pObj << std::endl;
delete foo.pObj;
foo.pObj = new int(13);
std::cout << *foo.pObj << std::endl;
delete foo.pObj;
}
我们可以将其转换为以下形式:
#include <iostream>
#include <memory>
struct Foo
{
std::unique_ptr<int> pObj;
Foo() : pObj(NULL) {}
};
std::unique_ptr<int> CreateObj()
{
return std::unique_ptr<int>(new int(42));
}
int main()
{
Foo foo;
foo.pObj = CreateObj();
std::cout << *foo.pObj << std::endl;
foo.pObj = std::unique_ptr<int>(new int(13));
std::cout << *foo.pObj << std::endl;
}
unique_ptr
包装器。这有几个优点:
unique_ptr
只能由当前范围拥有。当 createObj 创建对象时,通过返回临时(无名)unique_ptr
,它会释放所有权,以便调用者可以随时删除它。这将避免棘手的内存泄漏。unique_ptr
超出范围或被覆盖(例如被赋值运算符)时,删除会自动发生。是的,您可以重复使用指针。指针只是引用对象的一种方式。由于您删除了该对象,因此您可以随意使用指针来完成您需要的任何操作。
这样做绝对没有问题。指针只是地址的容器(类似于包含值的变量)。
new
分配一个对象并返回一个地址。然后,您可以将结果地址分配给您想要的任何指针(正确类型),无论它是 delete
d 指针、保存“现有”已分配对象的指针、保存 NULL 的指针还是未初始化的指针。
重用指针没有问题,只要首先释放先前分配的内存,就像您在代码中所做的那样。
当你
delete
一个指针时,你实际上释放了它指向的内存。指针的值(该内存的起始地址)保持不变,直到您通过 pointer = NULL
或 pointer = new ..
重新分配它
您可以重复使用该指针,因为您从未删除过该指针;您删除了指针所指向的
Obj
。请记住,指针存储的是内存地址。因此,就像您可以将 int 更改为不同的值一样,您始终可以更改指针以记住或指向不同的内存地址。另外,当您对 foo.pObj
执行删除操作时,您并不是说“删除 foo.pObj”。相反,你是说“删除 foo.pObj 指向的 Obj”。
如果您在执行
foo.pObj
操作后尝试对 delete
所指向的对象执行某些操作,则会出现问题。
是的,您可以重复使用它。 但就内存安全而言,存在一种可能的安全隐患。这是一个非常极端的情况。对于大多数应用程序来说,这不应该是一个问题。但在安全保障方面,你必须了解各方面的限制。
假设您的应用程序已经运行了很长时间,如果它经常重复使用相同的内存地址(指针重复使用)来绑定新对象,则某些恶意行为者有可能将任意代码/执行点注入到该特定对象上指针地址将使您的应用程序执行其代码,而不是应用程序附带的原始代码。
删除一个对象并将其设置为“nullptr”并通过调用 new 或任何其他奇特方法再次重新创建它后,该新分配可能会驻留在与前一个指针变量的地址不同的内存位置上(没有但可以保证,因为这样做是操作系统的责任(找到创建新对象等的适当位置)。