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

C++ 为什么这个智能指针在其目标应该被删除时给出正确的结果?,c++,smart-pointers,undefined-behavior,C++,Smart Pointers,Undefined Behavior,免责声明:我知道这不是独特的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

免责声明:我知道这不是独特的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;
}
void foo(int*a){
函数中唯一的指针(a);
}
这个主要功能是:

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;
}
int main(无效){
int*myInt=新的int(5);
主目录中唯一的指针(myInt);
foo(myInt);
库特
我不明白的是为什么第一个答案总是正确的

大多数实现不会在删除后清除内存或将其返回操作系统,因此,如果在删除后快速检查内存,则其未被覆盖的可能性更高

这是未定义行为的有效后果之一。它在您的特定实现上可能是100%可预测的,但在其他实现上不必如此

我不明白的是为什么第一个答案总是正确的

大多数实现不会在删除后清除内存或将其返回操作系统,因此,如果在删除后快速检查内存,则其未被覆盖的可能性更高

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

这不是一个好方法(足够纯粹)使用构造函数/析构函数或删除进行实验。如果对象未损坏,则并不意味着未调用
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);
....
}
#包括
MyObj类{
int值;
MyObj(int v):value(v){std::cerr用构造函数/析构函数或删除进行(足够纯)实验不是一个好方法。如果对象未损坏,并不意味着未调用
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);
....
}
#包括
MyObj类{
int值;

MyObj(int v):value(v){std::cerr没有正确的结果。您有未定义的行为。@Thomas Marshall我的假设是正确的,调用foo应该删除我的整数,因为函数中的指针\u超出了范围?yes@ThomasMarshall有些东西怎么可能是“更未定义的”?它是未定义的还是未定义的。@ThomasMarshall如果它是未定义的,你不能期望任何特定的结果。所有的赌注都没有。我建议阅读未定义的行为。一致的结果是未定义的行为表明没有正确结果的一种特殊方式。你有未定义的行为。@Thomas Marshall我的假设正确吗调用时,foo应该删除我的整数,因为函数中的指针超出范围?yes@ThomasMarshall有些东西怎么可能是“更未定义的”?它是未定义的还是未定义的。@ThomasMarshall如果它是未定义的,你就不能期望任何特定的结果。所有的赌注都没有了。我建议阅读未定义的行为。一致的结果是未定义的行为可以显化的一种特殊方式。你应该提到,它可能会工作很长一段时间-然后一个程序员会出现并做一些事情维护和故障您应该提到,它可能会工作很长一段时间-然后一个程序员来做一些维护和故障