为什么这个智能指针在其目标应该被删除时给出正确的结果?

时间:2017-04-30 07:55:41

标签: c++ smart-pointers undefined-behavior

免责声明:我知道不应该使用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超出范围?

2 个答案:

答案 0 :(得分:5)

  

我不明白为什么第一个cout一直给出正确的答案。

大多数实现在删除后都没有清除内存或将其返回给操作系统,所以如果你在删除后快速检查内存,那么它没有被覆盖的可能性会更高。

这是未定义行为的有效后果之一。它可能在您的特定实现上100%可预测,但在其他实现时不需要表现相同。

答案 1 :(得分:1)

使用构造函数/析构函数或删除进行(纯粹的)实验不是一个好方法。如果你有一个没有损坏的对象,它就意味着没有调用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);
....
}