指针复制到超出范围c ++

时间:2015-12-06 08:11:07

标签: c++ pointers vector scope

今天我回去调查了一个旧项目中的错误。这不是一个错误,相反,我不知道如何做我需要做的事情。不要真的想深入了解项目的细节,因为它已经过时,而且效率低,效率低,而且更重要的是无关紧要。所以我编写了一个新的示例代码:

#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
  4. 这是我用来解释第一个问题的图片(具体示例不是很准确,但问题是相同的),谢谢你的时间。 Here is a picture i made to visualize my main problem.

1 个答案:

答案 0 :(得分: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类所有。