我想如何跟踪我的差异指针(对象)。
例如,假设此代码(语言无关紧要,我在C ++和Python中都遇到相同的问题):
int *a = new int(2);
int *b = a;
delete a;
a = nullptr;
我想知道b不再可用了。我曾考虑过使用包装纸,但我认为这种解决方案缺乏优雅感。
你们知道更好的解决方案吗,例如某种簿记技术。
谢谢 !!!
最佳答案
实际上,语言确实很重要,因为某些语言可能会根据您定义和实现对象和对象生命周期等想法的方式来完成您想要的事情。实际上,许多语言使得不可能或几乎不可能拥有类似于悬挂指针或悬挂引用的内容。但是这个问题被标记为C ++,并且有一个C ++示例,并且C ++肯定没有在delete
表达式后进行这种检查的方法。
为什么不?因为C ++语言及其典型编译器的核心原则之一就是您不用为不使用的东西付费。在几乎所有计算机体系结构上,都可以以非常有效的方式获取C ++原始指针的方式来实现,但并未提供任何方式来保证或检查该内存实际上仍然有效并且不会为完全不同的用途重用。编译器可以自动添加额外的簿记功能,从而可以检查C ++指针对象是否有效,但这意味着在实际程序执行过程中不可避免地要进行额外的工作,这将显着降低所有程序的速度,即使在部分程序中使用这类检查。因此,C ++可以通过这种方式生成快速代码,但是存在要求程序正确使用指针的危险。
另一方面,C ++确实很容易实现各种包装程序和簿记功能,它们确实提供了所需的额外功能,例如所需的检查,并且仍然使用与熟悉的原始指针语法非常相似的语法。更好的是,在标准库中为您提供了一些最有用的包装模式。我们可能会以几种方式重写您的示例代码,并提供一条语句来实际尝试使用*b
:
使用std::unique_ptr
std::unique_ptr<int> a = std::make_unique<int>(2);
std::unique_ptr<int> b = a;
a = nullptr;
std::cout << *b;
结果:程序无法编译!
从
b
初始化a
是非法的,因为unique_ptr
中的“唯一”表示编译器将帮助您确保一次仅具有一个指向拥有对象的指针。并不是针对您所问的情况,而是实际上需要动态创建的对象,但每个对象只有一个指针,这也很普遍,它也控制对象的生存期。在这种情况下,关于unique_ptr
的一件好事是,它有助于避免意外创建其他指针,而这些指针最终可能会悬空。关于它的另一件好事是,您不需要任何等价的
delete
。如果unique_ptr
的生存期结束(例如,通过到达{
block }
的末尾,销毁具有unique_ptr
作为成员的对象或通过从容器中删除unique_ptr
),它将为您执行delete
。同样,如果您重新分配unique_ptr
指向其他内容,它将delete
先前指向的任何内容。因此,a = nullptr;
行是一种强制指针立即清除并忘记其对象的方法,但这通常不是必需的。所有这些都有助于避免泄漏,重复删除和悬空指针。顺便说一句,由于
unique_ptr
只是在编译时检查以避免在明确定义的位置进行复制和自动清理,因此使用它的程序通常可以编译成可执行文件,其执行速度与使用原始指针的程序一样快,< cc>和new
直接。减少了程序员的工作量和危险性。使用
delete
std::shared_ptr<int> a = std::make_shared<int>(2);
std::shared_ptr<int> b = a;
a = nullptr;
std::cout << *b;
结果:打印2。
std::shared_ptr
将簿记添加到指针,以便它始终知道存在该对象的指针。通常,只有在不再有指向该对象的shared_ptr
指针时,该对象才会被销毁。但是有时您不希望您的第二个副本真正使该对象保持活动状态。更改原始指针时,对象应消失,就像原始代码中一样。这将我们带入示例,就像原始代码一样:
使用
shared_ptr
和std::shared_ptr
std::shared_ptr<int> a = std::make_shared<int>(2);
std::weak_ptr<int> b = a;
a = nullptr;
if (std::shared_ptr<int> b_lock = b.lock())
std::cout << *b_lock;
else
std::cout << "b is null\n";
结果:打印“ b为空”。
std::weak_ptr
与weak_ptr
一起使用。当同时使用这两个指针时,指针指向的对象通常只有在不再有shared_ptr
指向它时才会被销毁。而且,当该对象被销毁时,指向该对象的所有shared_ptr
指针都会自动更改为空指针。需要
weak_ptr
调用和b.lock()
是因为您不能像shared_ptr b_lock
那样直接使用weak_ptr
。这是一项安全功能,因为如果您编写了代码来检查*b
不为null,然后又使用了b
,那么如果您在检查和使用之间调用的某些函数(或其他线程!)碰巧被破坏了,该怎么办?或更改*b
?相反,我们使用a
将lock()
转换回本地weak_ptr
,检查该指针是否为空,然后使用shared_ptr
。本地shared_ptr
保证该对象将继续存在足够长的时间,以用于将要使用它的代码,但此后不需要再停留了。因此,您可以通过这种方式检查指针是否仍然有效。
使用
shared_ptr
和shared_ptr
确实需要考虑一些条件,这些条件会导致它们指向的对象保持活动状态或允许对其进行清理,但是直接使用weak_ptr
和new
的设计也需要这样做。
关于c++ - 如何知道某个指针是否已在其他地方释放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51274220/