[問題]無法呼叫解構子

看板C_and_CPP作者 (小狼狼)時間15年前 (2010/08/21 01:04), 編輯推噓6(6047)
留言53則, 5人參與, 最新討論串1/1
( *[1m *[m 為色碼,可以按 Ctrl+V 預覽會顯示的顏色 ) ( 未必需要依照此格式,文章條理清楚即可 ) 遇到的問題: (題意請描述清楚) 無法呼叫解構子 希望得到的正確結果: 程式跑出來的錯誤結果: 開發平台: (例: VC++ or gcc/g++ or Dev-C++, Windows or Linux) VS2005 有問題的code: (請善用置底文標色功能) 請問各位大大,小弟宣告了一個class如下 class MyString { private: char *m_pstr; public: MyString(int len); MyString Fun(); ~MyString(); MyString& operator=(const MyString &str); }; MyString::MyString(int len) { m_pstr = new char[len]; } MyString::~MyString() { if (m_pstr != NULL) { delete[] m_pstr; m_pstr = NULL; } } MyString MyString::Fun() { MyString mystr(20); .... return mystr; } 當我宣告一個MyString mystr1(5), mystr2; 並執行到 mystr2 = mystr1.Fun(); 發現Fun()裡的 mystr不會呼叫解構子 請問各位大大,要如何才能呼叫到解構子 感謝 補充說明: -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 60.248.234.227

08/21 01:25, , 1F
我猜 compiler 幫你做了最佳化....
08/21 01:25, 1F

08/21 01:27, , 2F
先問一下, 你怎麼知道解構子沒有被呼叫? 因為就這程
08/21 01:27, 2F

08/21 01:27, , 3F
式碼看來, 並沒有default ctor & copy assignment
08/21 01:27, 3F

08/21 01:28, , 4F
編譯會不會過都是未知數
08/21 01:28, 4F

08/21 01:28, , 5F
如果沒有呼叫解構子的話記憶體沒delete
08/21 01:28, 5F

08/21 01:32, , 6F
這是有精簡過的code 真正的code有complier過可以跑
08/21 01:32, 6F

08/21 01:34, , 7F
我是在DEBUG時一行一行TRACE發現沒有執行destructor
08/21 01:34, 7F

08/21 01:59, , 8F
看起來很像是compiler做了RVO,有檢查建構次數跟解構次數嗎?
08/21 01:59, 8F

08/21 02:05, , 9F
如果是RVO, 這樣就等價於一行寫完了
08/21 02:05, 9F

08/21 02:09, , 10F
這兩行程式碼中間穿插其他指令, 這樣的情形應該是不會
08/21 02:09, 10F

08/21 02:09, , 11F
出現才對
08/21 02:09, 11F

08/21 09:19, , 12F
但是就算中間有其他程式碼也未必不能做NRV吧?
08/21 09:19, 12F

08/21 09:19, , 13F
RVO
08/21 09:19, 13F

08/21 11:44, , 14F
我覺得編譯器應該是把它當成MyString myst2=mystr1.Fu
08/21 11:44, 14F

08/21 11:46, , 15F
n(); 如果中間有其他程式碼, 就算Fun是inline, 也不可
08/21 11:46, 15F

08/21 11:47, , 16F
能重新建構 mystr2 吧?
08/21 11:47, 16F

08/21 12:03, , 17F
剛試了一下vs2008,果然只要在Fun()裡穿插其他指令RVO就消
08/21 12:03, 17F

08/21 12:04, , 18F
失了,不論debug和release mode皆同,我想vs2005應該也是
08/21 12:04, 18F

08/21 12:53, , 19F
這是我的測試 http://codepad.org/hbdRIKRx
08/21 12:53, 19F

08/21 12:54, , 20F
由於我對RVO並沒有研究 請問這是否為NRVO?
08/21 12:54, 20F

08/21 13:04, , 21F
加上constructor的測試http://codepad.org/BxGKmDSi
08/21 13:04, 21F

08/21 13:21, , 22F
另外..就算非inline(foo定義提出來)結果也是一樣~
08/21 13:21, 22F

08/21 13:26, , 23F
因為你的程式碼都是直接在定義的時候給敘述, 我指的是
08/21 13:26, 23F

08/21 13:26, , 24F
像PO那樣分開寫的情況, 如果沒有inline編譯器很難看出
08/21 13:26, 24F

08/21 13:27, , 25F
內部其實可以最佳化, 而不做任何事情, RVO分成兩類,
08/21 13:27, 25F

08/21 13:27, , 26F
具名的回傳值就稱作NRVO
08/21 13:27, 26F

08/21 13:29, , 27F
NRVO和一般RVO我還懂@@ 不過就算非inline結果也一樣啊||
08/21 13:29, 27F

08/21 13:29, , 28F
而且這樣就跟您所說的兩行程式碼中間穿插其他指令不會發生
08/21 13:29, 28F

08/21 13:30, , 29F
RVO不太符合吧...因為我不熟 所以要確認一下這是否為NRVO
08/21 13:30, 29F

08/21 13:32, , 30F
我是不知道原P程式真正的問題是什麼 只是就這點提出問題
08/21 13:32, 30F

08/21 13:32, , 31F
O
08/21 13:32, 31F

08/21 13:33, , 32F
你的屬於 NRV
08/21 13:33, 32F

08/21 13:34, , 33F
所以我這情況的確是named return value optimization?
08/21 13:34, 33F

08/21 13:34, , 34F
你的程式穿插其他程式碼, 結果也是一樣, 因為被操作的
08/21 13:34, 34F

08/21 13:35, , 35F
temp 實際上還是 s2, 但是po 程式不太一樣
08/21 13:35, 35F

08/21 13:37, , 36F
MyString mystr2; /**/ mystr2 = mystr1.Fun();
08/21 13:37, 36F

08/21 13:37, , 37F
可以請love大指點一下哪裡不一樣嗎?抱歉 沒仔細讀過RVO>"<
08/21 13:37, 37F

08/21 13:38, , 38F
如果中間沒有擺任何東西, 編譯器可能直接把它簡短成
08/21 13:38, 38F

08/21 13:39, , 39F
MyString mystr2 = mystr1.Fun(); 這樣不管是NRV RV都
08/21 13:39, 39F

08/21 13:39, , 40F
可以辦到, 中間如果多了其他對 mystr2 操作的程式碼
08/21 13:39, 40F

08/21 13:39, , 41F
哦哦 瞭了
08/21 13:39, 41F

08/21 13:40, , 42F
這樣會迫使 mystr2 先用default ctor建構好, 之後做的
08/21 13:40, 42F

08/21 13:41, , 43F
那行就是copy assignment
08/21 13:41, 43F

08/21 13:48, , 44F
測試出來的確如您所說 感謝您的解說~
08/21 13:48, 44F

08/21 13:53, , 45F
我手邊沒有VS2005所以無法測試 不過原PO的情況在gcc開到
08/21 13:53, 45F

08/21 13:54, , 46F
-O3也不會有RVO...
08/21 13:54, 46F

08/21 15:16, , 47F
其實2010 express & 2008 pro 開到 /Ox 也不會有 RVO
08/21 15:16, 47F

08/21 15:17, , 48F
XD 以上只是純屬想像, 尤其是對不完整的程式碼, 隔空
08/21 15:17, 48F

08/21 15:17, , 49F
抓藥也抓不出什麼東西...
08/21 15:17, 49F

08/21 20:11, , 50F
感謝大大們的討論 最後我發現原來是沒有加copy constructor
08/21 20:11, 50F

08/21 20:11, , 51F
加上去之後就可以呼叫destructor了
08/21 20:11, 51F

08/21 20:13, , 52F
MyString str2 = str1.Fun();會呼叫copy constructor
08/21 20:13, 52F

08/21 20:13, , 53F
而不是assign operator
08/21 20:13, 53F
文章代碼(AID): #1CRhMSx7 (C_and_CPP)