2015-12-06 69 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