2011-08-18 45 views
0

作爲我的previous question的續集,我想問下我的代碼在做錯了什麼。正確使用新的/刪除

的代碼,例如

void myclass1::myfun() 
{ 
myclass2* newVar = new myclass2(); 
/* other code and stuff */ 
myvector.push_back(newVar); // myvector is a member of myclass1 and is a std::vector<myclass2*> 
delete newVar; 
} 

但是當我運行它,myvector返回空,除非我註釋掉delete線。

我在做什麼錯?

回答

2

如前所述,當您已經釋放內存時,您無法訪問或更改內存。你必須注意在析構函數中刪除你的對象(或者一個額外的函數)。這裏有一個片斷,它會做到這一點:

// this function adds the object 
`void MyClass1::AddFun() 
{ 
    myClass2* Ptr = new myClass2(); // create new object via new-operator 
    myvector.push_back(Ptr); 
} 

// this function clears the entire vector 
void MyClass1::ClearAllContent() 
{ 
    while (myvector.empty() == false) 
    { 
    delete myvector[myvectory.size() - 1]; // free the last object in your vector 
    myvector.pop_back();     // pop_back reomves the "empty"-pointer 
    } 
} 
3

您只想在完全使用它時刪除該對象。一旦你刪除它,你不應該再次嘗試引用它。

在一個典型的情況下,你只是想把對象本身(而不是指向對象的指針)放在你的向量中。當你將它添加到矢量中時,它會創建一個對象的副本,並且在從矢量中刪除對象或矢量本身被銷燬時自動銷燬該對象。

+0

哦,對,我沒有注意到這一點。謝謝。如果我刪除了刪除線,那麼現在當矢量被刪除時會發生什麼?只有指針被刪除?謝謝 – Federico

+0

@Federico:是的。只有指針被刪除,而不是指針。除非你將這些指針包裝成「智能指針」,爲你處理'delete'。 – ereOn

+0

@ereOn:理解。問題是我無法將指針向量更改爲一個對象(要更改的代碼太多,太多太大的對象會在每個.push_back(如果要在每個.push_back中重新分配) ))。如何刪除矢量時刪除pointees?這些「智能指針」是什麼?他們是否正在建立或者我應該定義它們?再次感謝。 – Federico

1

C++不是C#或Java或其他。你正在使用原始指針,你可能不應該這樣做。當你刪除剛分配的對象時,它就消失了,不能再使用了。你存儲一個指向它的向量看起來持續超出了函數的作用域是一個錯誤。

1

您在堆上創建的myclass2一個實例,然後把它的指針到載體中。當你做delete newVar;你正在銷燬你剛創建的實例。但是你的向量仍然有一個指向該對象的指針,並且該指針不再有效。

當您不再需要堆上的對象時,您只應該調用delete

您的選項如下:

  1. 不要刪除對象。這意味着你必須在你的程序中的其他地方刪除它,當一切都完成使用它時。這可能很難協調,所以你需要使用智能指針。如果您正在編譯C++ 0x,您可以在Boost庫或標準庫中找到shared_ptr。下面是你會C++ 0x中使用它:

    #include <vector> 
    #include <memory> 
    #include <algorithm> 
    #include <iostream> 
    
    int main(int argc, const char* argv[]) { 
        typedef std::vector<std::shared_ptr<int>> Vector; 
    
        Vector v = { 
        Vector::value_type(new int(2)), 
        Vector::value_type(new int(5)) 
        }; 
    
        std::for_each(v.begin(), v.end(), [](Vector::value_type x) { 
        std::cout << *x << std::endl; 
        }); 
    
        return 0; 
    } 
    
  2. 不要在堆中分配的對象。相反,只需使用myclass的實例填充矢量,而不是指向myclass的指針。現在你的矢量將是一個std::vector<myclass2>

如果您有選擇,第二個選項更可取。當矢量被銷燬時,你的myclass2實例將被銷燬,這減輕了追蹤它們的麻煩。

2

newVar的析構函數被調用,當你調用delete時,由new分配的內存返回堆。

此時您不應該致電刪除。在myclass1的析構函數中或在其他成員函數中執行。

最佳實踐是:存儲在矢量值或智能指針像boost :: shared_ptr <>。智能指針適合您的情況。你甚至可以不用擔心刪除myvector的元素,因爲當myvector被破壞時它們會被正確地破壞。 示例代碼是:

void myclass1::myfun() 
{ 
    myvector.push_back(boost::shared_ptr<myclass2>(new myclass2())); 
}