考虑
void d(int* t) { //pointer passed by value
delete t;
std::cout << *t << '\n';
}
和
void d2(int*& t) { //pointer passed by reference
delete t;
std::cout << *t << '\n';
}
说我们有:
int *y = new int{22};
d(y);
d2(y);
在这两种情况下,我都预料到:
std::cout << *t << '\n';
导致未定义的行为,因为我应该删除t的值。但我仍然可以成功取消引用它,好像&#34;删除t;&#34;什么也没做。那是为什么?
答案 0 :(得分:3)
&#34;导致UB&#34; /&#34;但我仍然可以成功地取消引用它,好像&#34;删除t;&#34;什么也没做。为什么?&#34;
&#34;成功&#34;因为它可以编译,但不能成功地#34;如同在&#34;不必担心UB&#34;。为什么?因为编译器在编译期间没有尝试(或期望)建模运行时程序状态:确保程序在运行时不会尝试使用未定义的行为,这是你的工作。
在第二种情况下,我的理解是我通过引用传递它,所以仍然有一个指针指向y
不...你没有指向y
的任何信息......你引用了y
。无论如何,int
之后的delete t
不存在,反之亦然:当你复制指针时 - 调用d()
而不是d2()
},调用者的y
副本不受影响,并成为指向int
曾经存在的位置(完全没用)的悬空指针。此外,如果调用d(y);
,则d2(y);
在delete t;
语句中的行为未定义,而不仅仅是*t
。