受this question的启发。
假设在C ++代码中我有一个有效的指针并正确地delete
它。根据C ++标准,指针将变为无效(3.7.3.2/4 - 解除分配函数将使所有指针无效,指向释放存储的所有部分)。
至少在大多数实现中,它会保留该值并存储与delete
之前完全相同的地址,但是using the value is undefined behavior。
标准是否保证指针将保留其值或允许更改的值?
答案 0 :(得分:19)
不,它不能得到保证,并且实现可以合理地将左值操作数归零给delete
。
Bjarne Stroustrup曾希望实施会选择这样做,但并不是很多。
答案 1 :(得分:10)
如果出于某种原因,您希望确保指针变量未被delete
更改,请写:
delete p + 0;
答案 2 :(得分:3)
我相信大多数实现都会保留这个值,只是为了没有理由改变它。但无论值是否保留,它仍然是一个无用的指针,不是吗?
答案 3 :(得分:2)
全局运算符delete的签名,符合标准3.7.3.2/2:
的要求每个释放函数都应返回void,其第一个参数应为void *。
这意味着删除不能修改传递给它的指针,它将始终保留其值。
答案 4 :(得分:1)
除了分配指针的范围和超出该范围结束的指针之外,指针不能保证具有任何有意义的值。
您可能会质疑的是,您是否正在进行自己的泄漏检查,因此您在完成删除后编写了从地图中删除指针的功能。这将使用std :: less,它可以保证与指向范围内的指针一起工作,并且可能也会使用指向不再有效的内存的指针。
当然,在删除它指向的内存之前,您可能会收集垃圾进行“删除”。
与标准一样,如果传递给delete的值不是l值,则保证保持相同的值,但如果它是l值,则它是实现定义的。
答案 5 :(得分:1)
考虑一下,您如何检查或依赖任何“是”或“否”答案?你不能。或者,您可以,但检查的结果(nullpointer除外)是Undefined Behavior。
您无法在delete
之后检查非空值,因此问题通常是无意义。
此外,delete
的参数可以是右值表达式,因此问题毫无意义。
干杯&第h。,
答案 6 :(得分:1)
这个问题很重要! 我已经看到Visual Studio 2017在“删除”之后更改了指针值。它引起了一个问题,因为我使用了内存跟踪工具。该工具在每个操作员“新建”之后收集指针,并在“删除”之后检查它们。伪代码:
Data* New(const size_t count)
{
Data* const ptr(new Data[count]);
#ifdef TEST_MODE
DebugMemory.Collect(ptr);
#endif
return ptr;
}
void Delete(Data* const ptr)
{
delete[] ptr;
#ifdef TEST_MODE
DebugMemory.Test(ptr);
#endif
}
此代码在Visual Studio 2008上运行良好,但在Visual Studio 2017上失败,因此我更改了第二个功能的操作顺序。
但是,问题很好,并且存在问题。经验丰富的工程师应该意识到这一点。