2015-06-13 40 views
-1

在我的代碼中,我不明白爲什麼我的派生類對象沒有被銷燬,即使我明確調用了析構函數。我不知道它是否因爲我沒有包括刪除或與範圍有關,但你能幫我嗎?我在我的代碼添加了註釋,以幫助說明我的問題爲什麼我的析構函數不會銷燬我的對象,它仍然保留其成員變量值?

在我的頭文件我有:

#ifndef test_test_h 
#define test_test_h 

#include <iostream> 
#include <string> 

using namespace std; 


class test{ 
public: 
    test(); 
    void setName(); 
    string getName(); 
private: 
    string name; 
}; 

class book:public test{ 
public: 
    book(); 
    ~book(); 
    void setBook(); 
    string getBook(); 
private: 
    string bookName; 
}; 

#endif 

我在執行文件我有:

#include "test.h" 

test::test() 
{ 
    cout<<"calling base construtor"<<endl; 
    name="hi"; 

} 

book::book() 
{ 
    cout<<"Calling derived constructor"<<endl; 
    bookName="yolo"; 
} 


test::~test() 
{ 
    cout<<"calling test destructor"<<endl; 
} 


book::~book() 
{ 
    cout<<"calling book destructor"<<endl; 
} 




void test::setName() 
{ 
    cout<<"Input name"<<endl; 
    cin>>name; 

} 

string test::getName() 
{ 
    return name; 
} 

void book::setBook() 
{ 
    cout<<"Input name"<<endl; 
    cin>>bookName; 

} 

string book::getBook() 
{ 
    return bookName; 
} 

在我的主文件我有:

#include "test.h" 

int main(){ 


    book b; 

    b.setBook(); 

    cout<<b.getBook()<<endl;//takes user input 
    cout<<b.getBook()<<endl;//displays the input u put in 

    b.~book(); 

    cout<<b.getBook()<<endl;//for some reason it still prints out whatever you inputed even though I called the destructor earlier. I would think it would display yolo because that string is saved in the constructor of book 
} 
+2

不要直接打電話給dtor。它在對象被刪除時自動調用。這是你釋放對象所擁有的任何內存的地方。 – twentylemon

+0

@twentylemon這沒有回答我的問題哈哈。我的析構函數應該仍然刪除我的對象,但它沒有 – user5007232

+4

不,它不應該刪除對象。 'b'仍然在範圍內。你所做的只是調用名爲'〜book'的函數。 – twentylemon

回答

1

首先,不要爲具有自動存儲的變量明確調用析構函數。當您退出定義變量的作用域時,析構函數將自動調用。

之後你打電話,

b.~book(); 

b是一個無效的對象。

之後使用b會導致未定義的行爲。之後的線路並不能保證以任何可預測的方式行事。

您有:

cout<<b.getBook()<<endl;//for some reason it still prints out whatever you inputed even though I called the destructor earlier. I would think it would display yolo because that string is saved in the constructor of book 

由於該方案是受到不確定的行爲,這是毫無意義的努力使的它做什麼的感覺。

此外,函數返回時會調用b析構函數,這將導致未定義的行爲。

0

由於某種原因,它仍然會打印出您輸入的任何內容,即使我之前調用過析構函數。

析構函數方法不會釋放對象或清除成員變量使用的內存。這僅僅是您釋放實例生命週期內分配的資源的機會。

我想是因爲該字符串保存在書

也就是說這種情況發生的對象,不是最後的第一件事的構造,將YOLO顯示。對象的狀態在被銷燬後不會返回到構造的狀態;它是未定義的。最後一次更改可能會保留在內存中。

一旦對象被運行時銷燬,分配給它的內存內容就不確定。由於每當一個對象被銷燬時將內存清零可能是非常昂貴的,因此大多數實現會保留內存的內容,並且只會被稍後的使用覆蓋。這就是爲什麼在調用析構函數後能夠打印出書名的原因。

這裏是main功能,與一些意見註釋來說明:

#include "test.h" 

int main(){ 

    // 1. Allocate a book object on the stack 
    book b; 

    // 2. b.bookName = "yolo"  
    b.setBook(); 

    cout<<b.getBook()<<endl; 
    // 3. bookName = "user input" 

    // Wrong! But calls the destructor method which just prints a message 
    b.~book(); 

    // 4. displays "user input" 
    cout<<b.getBook()<<endl; 

    // b goes out of scope and ~book() will be called automatically 
} 

你應該手動調用析構函數。對於在堆棧中分配的對象(自動分配,如同這裏),當變量超出範圍(在塊的末尾)並且將調用析構函數時,對象將被銷燬。

對於在堆上分配的對象,通過調用delete來銷燬對象,該對象將爲您調用析構函數,然後將內存釋放回系統。這也不能保證將內存清零;它通常被標記爲未使用並可供重用。

您的代碼顯示相同的書名值,因爲book實例在打印時仍處於堆棧中,因爲手動調用析構函數實際上不會釋放或清零內存。

相關問題