• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 96  文章 - 255  trackbacks - 0
            <2008年4月>
            303112345
            6789101112
            13141516171819
            20212223242526
            27282930123
            45678910

            E-mail:zbln426@163.com QQ:85132383 長期尋找對戰略游戲感興趣的合作伙伴。

            常用鏈接

            留言簿(21)

            隨筆分類

            隨筆檔案

            SDL相關網站

            我的個人網頁

            我的小游戲

            資源下載

            搜索

            •  

            積分與排名

            • 積分 - 493126
            • 排名 - 39

            最新評論

            閱讀排行榜

            評論排行榜

                    幾乎在大部分時候,我們是不需要顯式的調用析構函數的。顯式的調用析構函數是一件非常危險的事情,因為如果系統會調用析構函數,無論我們自己是否已經調用過,仍然會再次調用。換句話說,我們自己所謂的顯式調用析構函數,實際上只是調用了一個成員函數,并沒有真正意義上的讓對象“析構”。
                    為了理解這個問題,我們必須首先弄明白“堆”和“棧”的概念。
            堆區(heap) —— 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收 。注意它與數據結構中的堆是兩回事,分配方式倒是類似于鏈表。
            棧區(stack)—— 由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似于數據結構中的棧。
                    我們構造對象,往往都是在一段語句體中,比如函數,判斷,循環,還有就直接被一對“{}”包含的語句體。這個對象在語句體中被創建,在語句體結束的時候被銷毀。問題就在于,這樣的對象在生命周期中是存在于棧上的。也就是說,如何管理,是系統完成而程序員不能控制的。所以,即使我們調用了析構,在對象生命周期結束后,系統仍然會再調用一次析構函數,將其在棧上銷毀,實現真正的析構。
                    所以,如果我們在析構函數中有清除堆數據的語句,調用兩次意味著第二次會試圖清理已經被清理過了的,根本不再存在的數據!這是件會導致運行時錯誤的問題,并且在編譯的時候不會告訴你!
            在網上找到這幾句話,說得很好啊:
            //顯式調用的時候,析構函數相當于的一個普通的成員函數
            //編譯器隱式調用析構函數,如分配了對內存,顯式調用析構的話引起重復釋放堆內存的異常
            //把一個對象看作占用了部分棧內存,占用了部分堆內存(如果申請了的話),這樣便于理解這個問題
            //系統隱式調用析構函數的時候,會加入釋放棧內存的動作(而堆內存則由用戶手工的釋放)
            //用戶顯式調用析構函數的時候,只是單純執行析構函數內的語句,不會釋放棧內存,摧毀對象

                    系統在什么情況下不會自動調用析構函數呢?顯然,如果對象被建立在堆上,系統就不會自動調用。一個常見的例子是new...delete組合。但是好在調用delete的時候,析構函數還是被自動調用了。很罕見的例外在于使用布局new的時候,在delete設置的緩存之前,需要顯式調用的析構函數,這實在是很少見的情況。
                    所以,結論是,一般不要自作聰明的去調用析構函數。或者要是你不嫌麻煩的話,析構之前最好先看看堆上的數據是不是已經被釋放過了。放出一個演示的例子,大家可以參考一下哈。

            #ifndef A_HPP
            #define A_HPP

            #include 
            <iostream>
            using namespace std;

            class A
            {
            private:
                
            int a;
                
            int* temp;
                
            bool heap_deleted;
            public:
                A(
            int _a);
                A(
            const A& _a);
                
            ~A();
                
            void change(int x);
                
            void show() const;
            };

            #endif


             

            #include "a.hpp"

            A::A(
            int _a): heap_deleted(false)
            {
                temp 
            = new int;
                
            *temp = _a;
                a 
            = *temp;
                cout
            << "A Constructor!" << endl; 
            }

            A::A(
            const A& _a): heap_deleted(false)
            {
                temp 
            = new int;
                
            *temp = _a.a;
                a 
            = *temp;
                cout 
            << "A Copy Constructor" << endl;
            }

            A::
            ~A()
            {
                
            if ( heap_deleted == false){
                    cout 
            << "temp at: " << temp << endl;
                    delete temp;
                    heap_deleted 
            = true;
                    cout 
            << "Heap Deleted!\n";
                }
                
            else {
                    cout 
            << "Heap  already Deleted!\n";
                }

                cout 
            << "A Destroyed!" << endl; 
            }

            void A::change(int x)
            {
                a 
            = x;
            }

            void A::show() const
            {
                cout 
            << "a = " << a << endl;
            }

            #include "a.hpp"

            int main(int argc, char* argv[])
            {

                A a(
            1);
                a.
            ~A();
                a.show();
                cout 
            << "main() end\n";
                a.change(
            2);
                a.show();

                
            return 0;
            }
            posted on 2008-04-12 14:29 lf426 閱讀(2497) 評論(1)  編輯 收藏 引用 所屬分類: 語言基礎、數據結構與算法

            FeedBack:
            # re: 顯式析構函數的陷阱 2008-10-24 20:54 林楚濤
            當用placement new 創建對象的時候就必須自己顯式調用析構函數  回復  更多評論
              
            精品无码人妻久久久久久| 亚洲第一永久AV网站久久精品男人的天堂AV | 99精品久久精品一区二区| 伊人久久综合无码成人网| 久久天天躁狠狠躁夜夜avapp| 国产欧美一区二区久久| 久久久WWW成人| 国产亚洲综合久久系列| 综合久久给合久久狠狠狠97色| 久久亚洲私人国产精品vA| 日本国产精品久久| 99热成人精品免费久久| 无码久久精品国产亚洲Av影片| 国产综合免费精品久久久| 久久99精品久久久久婷婷| 超级碰碰碰碰97久久久久| 99久久99久久精品国产片| 国产69精品久久久久9999APGF| 国内精品伊人久久久久影院对白| 色综合久久久久综合体桃花网| 久久伊人色| 久久久久久久久久久免费精品| 国产一区二区三区久久| 亚洲AV日韩精品久久久久久| 无夜精品久久久久久| 久久国产精品免费| 国产ww久久久久久久久久| 免费精品99久久国产综合精品| 国产成人无码久久久精品一| 久久久无码一区二区三区| 亚洲愉拍99热成人精品热久久| 亚洲午夜久久久| 日本五月天婷久久网站| 一极黄色视频久久网站| 麻豆久久久9性大片| 色播久久人人爽人人爽人人片AV| 久久精品国产WWW456C0M| 无码国内精品久久人妻麻豆按摩| 久久久久亚洲爆乳少妇无| 怡红院日本一道日本久久 | 青青草国产成人久久91网|