• <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 創建對象的時候就必須自己顯式調用析構函數  回復  更多評論
              
            亚洲欧美成人综合久久久| 99久久免费国产精品| 伊人情人综合成人久久网小说 | 国产成人综合久久精品尤物| 精品国产青草久久久久福利 | 亚洲精品美女久久久久99| 久久国产亚洲高清观看| 精品久久久久国产免费| 色欲综合久久躁天天躁蜜桃| 伊人丁香狠狠色综合久久| 久久久SS麻豆欧美国产日韩| 夜夜亚洲天天久久| 久久精品国产亚洲AV无码麻豆| 久久精品国产福利国产琪琪| 热re99久久6国产精品免费| 久久人妻少妇嫩草AV无码蜜桃| 久久99精品久久久久久久久久| 日韩精品久久久久久久电影| 狠狠综合久久综合中文88| 久久这里只有精品18| 午夜福利91久久福利| 伊人热人久久中文字幕| 久久精品国产影库免费看| 亚洲国产另类久久久精品| 日韩人妻无码一区二区三区久久99| 亚洲国产成人久久综合一| 久久久久久久久无码精品亚洲日韩 | 91精品国产91久久久久久青草| 亚洲精品无码久久久久去q| 无码任你躁久久久久久老妇| 久久久艹| 亚洲国产精品成人AV无码久久综合影院 | 久久九九久精品国产| 国产一区二区精品久久凹凸 | 精品久久久久久国产| 久久久无码精品亚洲日韩按摩 | 97精品伊人久久久大香线蕉| 久久免费高清视频| 狠狠久久综合| 国产亚洲精久久久久久无码77777 国产亚洲精品久久久久秋霞 | 久久综合狠狠综合久久97色|