[英]Pass a pointer as argument to a function
考慮以下示例
class Foo{
public:
Foo(int i):x(i){}
int x;
};
void
bar(Foo *p2)
{
delete p2;
p2 = new Foo(2);
}
int
main()
{
Foo *p1 = new Foo(1);
cout<<p1->x;
bar(p1);
cout<<p1->x;
}
據我了解,指針變量存儲在堆棧中,並包含指向它“指向”的堆上動態分配的內存的地址。 現在,當我將指針傳遞給函數時,將在堆棧上創建第二個指針,指向與第一個指針相同的內存地址。 當我在bar()中刪除p2並分配新的內存時,p1和p2應該指向不同的地址,對嗎?
但是,如果我編譯此代碼,則會得到1和2作為輸出。 這是因為p2設法分配了p1已經指向的同一存儲單元,還是我錯過了某些東西?
這是因為p2設法分配了p1已經指向的同一存儲單元,還是我錯過了某些東西?
你什么都沒錯過 您已正確確定該程序的行為是undefined 。 根據定義,它可以打印所有內容,包括2
。
在您的運行中,只有巧合(很可能是您確定的巧合)才使它打印2
。 您可以通過在delete
和現有new
之前添加new int(47)
來中斷該巧合鏈。
如果您希望程序按照其行為方式進行操作,但希望通過已定義的行為進行操作,則可以對bar
的定義進行以下小的更改:
void
bar(Foo*& p2)
這將通過引用而不是通過值傳遞參數。 這樣,對bar
內部變量p2
更改將反映在`main內部的p1
。
除了您的示例外,指針變量不一定位於堆棧上,它們引用的地址也不一定位於堆上(但是new和malloc都返回堆上的地址)。 指針變量及其引用的地址都可以在堆棧,堆,全局/靜態變量區域甚至ROM上。 其余的解釋是正確的,但觀察到的行為尚不確定,並且期望其可重復是非常危險的。 任何更改,不同的運行時版本,多線程情況,在不同體系結構上進行編譯或在其他編譯器上進行的編譯都可以完全改變結果:隨機值或崩潰。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.