簡體   English   中英

析構函數被提前調用

[英]Destructor being called early

我有一個隊列類,其中我試圖動態分配3個“示例”對象並將它們放入隊列,然后出列並刪除它們。 但是樣本對象的析構函數:

~Sample() { cout << "Destructing Sample object " << id << "\n"; }

由於某種原因,當我嘗試將對象放在隊列中時被調用。

int main()
{
   Sample *samp1;
   Sample *samp2;
   Sample *samp3;
   Queue<Sample> sQa(3);
   samp1 = new Sample(1);
   samp2 = new Sample(2);
   samp3 = new Sample(3);

   cout << "Adding 3 Sample objects to queue...\n";

   sQa.put(*samp1);
   sQa.put(*samp2);
   sQa.put(*samp3);

   cout << "Dequeing and destroying the objects...\n";

   for(int i = 0; i < 3; ++i)
   {
       delete &sQa.get();
   }

   return 0;
}

這是輸出:

Adding 3 sample objects to queue...
Destructing Sample object 1
Destructing Sample object 2
Destructing Sample object 3
Dequeing and destroying the objects...
Destructing Sample object 1

然后程序崩潰了。 誰知道為什么會這樣? 此外,這是必要的put函數。 (隊列類是模板)

void put(Qtype data) 
{
    if(putloc == size) 
    {
        cout << " -- Queue is full.\n";
        return;
    }

    putloc++;
    q[putloc] = data;   
}

您的代碼會導致未定義的行為。 它對未使用new動態分配的對象調用delete

附:

sQa.put(*samp1);

您在sQa存儲動態分配的成員的sQa 按值復制對象后,丟失了指向動態分配對象的指針。

解決方案是使用智能指針作為容器元素,讓RAII為您完成所有內存管理工作。

問題的根源

delete &sQa.get();

您正在刪除與new分配的對象無關的內容。

正確的方法如下:

Queue<Sample*> sQa(3);
samp1 = new Sample(1);
samp2 = new Sample(2);
samp3 = new Sample(3);

sQa.put(samp1);
sQa.put(samp2);
sQa.put(samp3);

cout << "Dequeing and destroying the objects...\n";

for(int i = 0; i < 3; ++i)
{
   delete sQa.get();
}

注意:最好使用諸如unique_ptrshared_ptr類的智能指針代替裸指針。

除非Qtype是typedef,否則put()函數指定其參數應該通過副本傳遞。 無論何時調用它,它都會調用Sample的復制構造函數來創建臨時對象。

你編碼分配對象; 將它們復制到隊列中; 從隊列中檢索副本; 並嘗試刪除這些副本。 原始對象被泄露(因為您不delete samp1等),並且最終對象無法刪除,因為它們不是用new創建的。

您看到的析構函數來自在將已分配的對象復制到隊列時創建的臨時對象; 崩潰是從刪除錯誤對象中獲得的未定義行為。

由於隊列包含對象而不是指針,因此根本不需要動態分配:

cout << "Adding 3 Sample objects to queue...\n";

sQa.put(Sample(1));
sQa.put(Sample(2));
sQa.put(Sample(3));

cout << "Dequeing and destroying the objects...\n";

for(int i = 0; i < 3; ++i)
{
   sQa.get();
}

如果你想試驗動態分配,那么你應該修改隊列來存儲指針; 但請記住,在沒有RAII幫助的情況下管理動態對象非常困難,所以不要在任何需要可靠的代碼中嘗試這一點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM