指標操作超越變數作用範圍的問題(高質量c )

2021-04-02 10:22:44 字數 2460 閱讀 8244

下面這是高質量c++上的:

指標操作超越了變數的作用範圍。這種情況讓人防不勝防,示例程式如下:

class a

};void test(void)

p->func(); // p 是「野指標」

}函式test 在執行語句p->func()時,物件a 已經消失,而p 是指向a 的,所以p 就

成了「野指標」。

但執行這個程式沒出錯。書上說原因是a雖然退棧了,但僅僅是呼叫了一下析構函式而已,而析構函式其實沒幹什麼重要的事情,它並沒有清楚a的記憶體,所以a仍然好好地在那裡放著,只是你無法在程式外直接訪問而已。

-------------

怎麼說析構函式沒幹什麼事情?析構函式不會清楚a的記憶體?誰給解釋下上面的原因

析構函式也是乙個函式, 只是不用程式設計師自己顯示呼叫, 在離開區域性變數的作用域的時候, 首先將按照變數宣告的逆序呼叫析構函式, 然後釋放區域性變數的記憶體空間。仍然使用釋放後的記憶體空間的行為是未定義的。

=========================================

由於a物件是在語句塊中,所以出了語句塊,a物件自動呼叫了析構函式,銷毀了物件,但是p指向的記憶體沒有變,只是那塊記憶體已經不被程式所控制,他可能隨時被修改,再分配。析構函式所作的只是告訴程式,這塊記憶體已經不再為物件a所用,但是並沒有把其中內容擦除,(我想這也是我們申請變數要初始化的原因吧 )

所以程式能執行出結果,也不足為怪,但是就穩定性來說,是大忌,因為極有可能你執行出來的結果可能被修改掉了,而這時候你卻誤認為是正確的。

=========================================

主要的原因是a類的func是個幾乎與a類無關的函式,如果a類這樣定義,**是會出錯的

class a

int num;

};這是因為函式裡面要引用它的成員變數,但是卻被析構了,類函式裡面呼叫的隱含this指標無效。

其實樓主的**寫成以下的樣子也能無錯的跑

a *p;

p->func();

主要的原因是a類的func是個幾乎與a類無關的函式,如果a類這樣定義,**是會出錯的

class a

int num;

};這是因為函式裡面要引用它的成員變數,但是卻被析構了,類函式裡面呼叫的隱含this指標無效。

其實樓主的**寫成以下的樣子也能無錯的跑

a *p;

p->func();

=======================================

我要是建立物件a a;當a離開作用域銷毀時,呼叫析構函式,只是釋放了a物件,a.num這塊記憶體的內容還是存在的(沒被析構函式清除?)?只是a不存在了,不能再訪問num對應這塊記憶體了?

*************************=

當釋放了a物件,a.num這塊記憶體還沒改變的時候,也還能通過指標訪問到這塊記憶體,讀出正確的內容。但這塊記憶體已不在程式控制之下了。假如是個多執行緒程式,a執行緒剛剛釋放這塊記憶體,b執行緒馬上又分配一塊記憶體,就可能用到a執行緒剛剛釋放的這塊記憶體,這時a執行緒訪問這塊記憶體的野指標訪問到的就是非法內容了。其實這個問題,如果寫成函式外通過指標訪問函式內的區域性變數應該更好理解。這是我的理解。

========================================

所謂的a析構了,即物件a占用的空間已經釋放,釋放並不會改變原來空間中的任何內容,只是可以再次分配使用而已。所以p雖然指向的空間已經釋放,但是它指向的資料還是有效的(還是使用者想要的),但是這樣畢竟不是總是安全的。

程式可以正常執行的另乙個原因為。類a中沒有任何的資料,p->func();在編譯就繫結了。我們可以先面的兩個例子說明:

#include

class a

void func(void)

};void test(void)

p->func(); // p 是「野指標」

}int main()

結果:44

結果正確,雖然a已經析構,但是a的內容仍然存在。

#include

class a

void func(void)

};void test(void)

p->func(); // p 是「野指標」

}int main()

結果:45

結果不正確,a已經析構,但是a的內容已經被int a的值5覆蓋掉了。

#include

class a

void func(void)

};void test(void)

p->func(); // p 是「野指標」

}int main()

結果:outputoutput

結果正確,因為類a中沒有資料,所以物件的存在沒有任何實際的意義,因為物件沒有狀態。

p->func().不會修改物件,所以正確。

變數的作用範圍

1.類中所有變數的預設修飾符是private。2.區域性變數必須先初始化才能使用,全域性變數 類的成員變數 可以不初始化,預設值為0 1 static void main string args 212 else 1316 17console.readkey 18 1920 static int n...

變數的作用範圍

看標題我們就差不多明白了整個意思 其實變數的作用範圍很簡單 就一句話 變數只能在當前大括號以及子括號內使用 這東西看起來不太好理解 在此分別列舉了三種情況 1.變數定義在main方法的括號內 2.定義在main方法的子括號內 3.定義在乙個自定義的方法內 也分別在三個地方嘗試去使用這個變數 1.ma...

js變數的作用範圍

前言 寫著寫著專案,看著日益繁多的js變數,突然對js變數的作用範圍產生了興趣,所以來研究一下,鑑於本人主要是搞後端的,這個主要是入門級js變數範圍介紹.目錄 第一章 不同script塊中的js變數 1.1 先定義 1.2 後定義 1.3.1 另一種定義方式 第二章 定義在js檔案中的變數 2.1 ...