当它的目标应该被删除时,为啥这个智能指针会给出正确的结果?
Posted
技术标签:
【中文标题】当它的目标应该被删除时,为啥这个智能指针会给出正确的结果?【英文标题】:Why does this smart pointer give the correct result when its target should have been deleted?当它的目标应该被删除时,为什么这个智能指针会给出正确的结果? 【发布时间】:2017-04-30 07:55:40 【问题描述】:免责声明:我知道这不是 unique_ptr 应该如何使用,但为了理解起见,我想知道这里发生了什么。谢谢!
考虑这个函数:
void foo(int* a)
unique_ptr<int> pointer_in_function(a);
还有这个主要功能:
int main(void)
int* myInt = new int(5);
unique_ptr<int> pointer_in_main(myInt);
foo(myInt);
cout << *pointer_in_main << endl;
cout << *pointer_in_main << endl;
cin.get();
return 0;
我始终从第一个 cout 中得到正确答案。第二个是未定义的。程序有时在退出时会因严重错误而崩溃,但并非总是如此。
我不明白为什么第一个 cout 始终给出正确答案。当pointer_in_function超出范围时,myInt指向的整数不应该被删除吗?感谢您的帮助!
编辑:顺便说一句,为了确定,我是否正确地假设调用 foo 应该删除我的整数,因为 pointer_in_function 超出范围?
【问题讨论】:
没有正确的结果。您有未定义的行为。 @Thomas Marshall 我是否正确地假设调用 foo 应该删除我的整数,因为 pointer_in_function 超出范围?是的 @ThomasMarshall 怎么会有“更不确定”的东西?未定义或未定义。 @ThomasMarshall 如果它是未定义的,你不能期待任何特定的结果。所有的赌注都取消了。我建议阅读未定义的行为。 一致的结果是未定义行为表现出来的一种特殊方式 【参考方案1】:我不明白为什么第一个 cout 始终给出正确答案。
大多数实现在删除后不会清除内存或将其返回给操作系统,因此如果您在删除后快速检查内存,它尚未被覆盖的可能性会更高。
这是未定义行为的有效后果之一。它可能在您的特定实现上是 100% 可预测的,尽管它在其他实现上的行为不一定相同。
【讨论】:
你应该提到它可能会工作很长一段时间 - 然后程序员会出现并进行一些维护并且事情会中断【参考方案2】:用构造函数/析构函数或删除进行(足够纯粹)实验不是一个好方法。如果您有一个未损坏的对象,它并不意味着尚未调用 delete
运算符(因为它对内存数据的影响是未定义的,并且确实许多内存管理器实现不会立即更改释放的内存内容)。相反,创建一个具有显式构造函数和析构函数的类来报告它们的调用,并使用它来代替int
。由于析构函数调用预先考虑了对象删除(并且由于您的代码不使用堆栈或被测对象的静态分配,因此析构函数调用始终意味着删除),您可以使用析构函数调用来跟踪删除。比如:
#include <iostream>
class MyObj
int value;
MyObj(int v) : value(v) std::cerr << "MyObj ctor called"<<std::endl;
~MyObj() std::cerr << "MyObj dtor called"<<std::endl;
;
.....
int main (int argc, char **argv)
MyObj* myInt = new MyObj(5);
....
【讨论】:
以上是关于当它的目标应该被删除时,为啥这个智能指针会给出正确的结果?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 C# 'is' 运算符在比较两个布尔值时会给出正确的结果,我应该使用它吗?