2015-12-06 115 views
1

今天我回去調查了一箇舊項目中遇到的錯誤。這不完全是一個錯誤,相反,我不知道如何去做我需要做的事情。不要真的想進入項目的細節,因爲它是舊的,越野車,低效率,更重要的是無關緊要。所以我編碼了一個新的示例代碼:指針複製到範圍外C++

#include <iostream> 
#include <vector> 
#include <time.h> 
#include <random> 
#include <string> 

class myDoc; 

class myElement 
{ 
    int myInt; 
    std::string myString; 
    myElement * nextElement; 
    //a pointer to the element that comes immediately after this one 
public: 
    myElement(int x, std::string y) : myInt(x), myString(y){}; 
    friend myDoc; 
};//an element type 

class myDoc 
{ 
    std::vector<myElement> elements; 
public: 
    void load(); 
    ~myDoc() 
    { 
     //I believe i should delete the dynamic objects here. 
    } 
};// a document class that has bunch of myElement class type objects as members 

void myDoc::load() 
{ 
    srand(time(0)); 
    myElement * curElement; 
    for (int i = 0; i < 20; i++) 
    { 
     int randInt = rand() % 100; 
     std::string textInt = std::to_string(randInt); 
     curElement = new myElement(randInt,textInt); 
     //create a new element with a random int and its string form 

     if (i!=0) 
     { 
      elements[i-1].nextElement = curElement; 
      //assign the pointer to the new element to nextElement for the previous element 
      //!!!!!!!!!!!! this is the part that where i try to create a copy of the pointer 
      //that goes out of scope, but they get destroyed as soon as the stack goes out of scope 
     } 

     elements.push_back(*curElement);// this works completely fine 
    } 
} 

int main() 
{ 
    myDoc newDoc; 
    newDoc.load(); 
    // here in newDoc, non of the elements will have a valid pointer as their nextElement 
    return 0; 
} 

基本概要:我們有一個文檔類型,它由我們定義的元素類型的向量組成。在這個例子中,我們將20個隨機動態分配的新元素加載到文檔中。 我的問題/問題:

  1. void myElement::load()函數結束時,指針和/或它超出的範圍和被刪除的副本。至少在它指向的對象被刪除之前,我如何保留一個保留的副本(不完全是靜態的,是嗎?)?
  2. elements矢量中的對象,它們是原始動態分配的對象還是它們只是一個副本?
  3. 我用new分配內存,他/她應該如何/何時應該delete

這是我畫的第一個問題(對於具體例子不是很準確,但問題是相同的),並感謝您的時間。 Here is a picture i made to visualize my main problem.

+0

請發佈[最小,完整和可驗證的示例](http://stackoverflow.com/help/mcve) - 比某種東西或其他東西好得多。 –

回答

1

注:我以爲你想要一個向量myElement對象,其中每個對象指向它旁邊的元素。如果你想在elements的對象指向它們的副本,目前還不清楚,反正它應該是很容易修改代碼以實現後者

這是你的代碼會發生什麼:

void myDoc::load() 
{ 
    .. 
    curElement = new myElement(n,m); // Create a new element on the heap 

    ... 
    // If this is not the first element we inserted, have the pointer for the 
    // previous element point to the heap element 
    elements[i-1].nextElement = curElement; 

    // Insert a COPY of the heap element (not the one you stored the pointer to) 
    // into the vector (those are new heap elements copied from curElement) 
    elements.push_back(*curElement);// this works completely fine 
} 
myDoc::load()超出範圍,因爲指針沒有指向在 elements載體,但在你分配的第一要素堆元素

因此沒有被刪除,但你必須內存泄漏錯誤

這也回答你的第二個問題:他們是副本。

爲了自動釋放你的記憶,有沒有泄漏,並指向正確的元素,你可能會在自析構函數中做一些像

class myElement 
{ 
    int a; 
    std::string b; 
    myElement *nextElement = nullptr; 
    //a pointer to the element that comes immediately after this one 
public: 
    myElement(int x, std::string y) : a(x), b(y){}; 
    friend myDoc; 
};//an element type 

class myDoc 
{ 
    std::vector<std::unique_ptr<myElement>> elements; 
public: 
    void load(); 
    ~myDoc() 
    {} 
};// a document class that has bunch of myElement class type objects as members 

void myDoc::load() 
{ 
    srand((unsigned int)time(0)); 
    for (int i = 0; i < 20; i++) 
    { 
    int n = rand() % 100; 
    std::string m = std::to_string(n); 
    //create a new element with a random int and its string form 
    elements.emplace_back(std::make_unique<myElement>(n, m)); 

    if (i != 0) 
    { 
     //assign the pointer to the new element to nextElement for the previous element 
     elements[i - 1]->nextElement = elements[i].get(); 
    } 
    } 
} 

Live Example

無需delete什麼當myDoc元素超出範圍時,智能指針將自動銷燬(並釋放內存)。我相信這可能是你想要做的,因爲無論如何,這些元素歸myDoc類所有。

+0

謝謝你的回答,這真的很有幫助。謝謝你的微妙更正。一件小事,當時,這是一個家庭作業項目,我不允許使用智能指針。你認爲沒有他們的解決方案可能/值得調查嗎? – user3402183

+0

@ user3402183當然,您可以自己分配內存並管理析構函數中的釋放。你可以創建一個'std :: vector ',並讓元素指向向量中的其他元素(C++ 11提供就地構造),或者直接使用'std :: vector '來管理所有分配(除了向量中包含的指針外)你自己 –

+0

非常感謝,現在我明白了。 – user3402183