這是一個懸空指標
Foo* p;
{
Foo f;
p = &f;
}
// now p is dangling pointer
但是,為什么這不是一個懸空指標?
Foo* p;
{
Foo f;
...
*p = f;
}
// p still contains the data of f
是不是因為在第二種情況下,我們正在做一個副本?這是否意味著我應該寫
*p = std::move(f);
如果我不想要副本?
謝謝!
uj5u.com熱心網友回復:
在你的第二個例子中p是未初始化的。取消參考未初始化的指標是未定義的行為。
uj5u.com熱心網友回復:
首先,通過給出p一個有效的值來明確定義行為(不要讓事情未初始化是最簡單、最便宜的錯誤預防形式):
Foo* p = new Foo;
{
...
或者
Foo x;
Foo* p = &x;
{
...
現在,在您的第一段代碼中,p存盤f已被銷毀的的位置。
這就是使它成為懸空指標的原因。
在第二個,你不改變p,但保存價值的f中*p,這是同一個物件,因為它總是為。
由于該物件仍然存在,指標沒有懸空。
比較這兩個片段:
int x = 0;
int* p = &x;
{
int y = 1;
p = &y;
}
std::cout << "p: " << p << ", &x: " << &x;
和
int x = 0;
int* p = &x;
{
int y = 1;
*p = y;
}
std::cout << "p: " << p << ", &x: " << &x;
你會看到第一個列印了兩個不同的地址,第二個列印了兩次相同的地址。
uj5u.com熱心網友回復:
區別 - 如果有的話 - 取決于您對“懸空指標”的定義。它非常學術。
討論一種可能的定義。 懸空指標的一種可能定義是“指向不再有效資料的指標”。
根據該定義,您的第一個示例;
Foo* p; { Foo f; p = &f; } // now p is dangling pointer
結果p是一個懸空指標,因為它指向 object f,并且f在其封閉范圍(即})的末尾不再存在。由于p仍然存在,并且其值在f不復存在的程序中沒有改變,p現在指向一個不再存在的物件。
根據相同的定義,您的第二個示例;
Foo* p; { Foo f; ... *p = f; } // p still contains the data of f
不會產生懸空指標,因為p從未指向有效物件。事實上,p是未初始化的,所以簡單地訪問它的值會產生未定義的行為并且它的值(如果有的話)是不確定的。*p不求值就不能解參考(即求值),p因此運算式*p和陳述句*p = f都給出未定義的行為。*p在}導致未定義行為之后做任何事情(就像在你的第一個例子中所做的那樣)。
有了這個定義,第p一個例子中的懸空指標和第二個例子中的懸空指標的區別有點學術性。不同之處在于,在第一種情況下,p被視為懸空指標,因為它不再指向有效物件,但在第二種情況下,p不被視為懸空指標,因為它從未指向有效物件。實際上,區別沒有區別,因為做任何事情*p都會產生未定義的行為。
討論第二 個可能的定義 懸空指標的第二個可能定義與第一個“指向無效資料的指標”略有不同。
根據第二個定義,您的兩個示例都生成了一個懸空指標。第一個原因p指向一個不再存在的物件 - 所以它指向無效資料。在第二個示例中,p從未指向有效物件 - 因此它也指向無效資料。根據懸空指標的這個定義,在兩個示例中都是p在 之后的懸空指標,}因為它現在指向一個無效物件。
這第二個定義下的區別仍然是學術性的。簡單地評估*p(更不用說使用它來更改無效的物件p點,例如,*p = some_Foo)會給出未定義的行為。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/349712.html
上一篇:向量迭代器行為不正常
下一篇:帶有基類指標的成員向量
