user3402183
user3402183

Reputation: 432

Pointer Copy to Out of Scope c++

Today i went back and investigated an error i got in an old project. It's not exactly an error, rather, i don't know how to do what i need to do. Don't really want to go into the details of the project as it is old and buggy and inefficient and more importantly irrelevant. So i coded a new sample code:

#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;
}

Basic rundown: we have a document type that consists of a vector of element type we define. And in this example we load 20 random dynamically allocated new elements to the document. My questions/problems:

  1. When the void myElement::load() function ends, the pointer and/or the copies of it goes out of scope and get deleted. How do i keep a copy that stays(not quite static, is it?) at least until the object it points to is deleted?
  2. The objects in the elements vector, are they the original dynamically allocated objects or are they just a copy?
  3. I allocate memory with new, how/when should i delete them?

Here is a picture i painted to explain 1st problem(not very accurate for the specific example but the problem is the same), and thank you for your time. Here is a picture i made to visualize my main problem.

Upvotes: 1

Views: 838

Answers (1)

Marco A.
Marco A.

Reputation: 43662

Note: I assumed you want a vector of myElement objects where each one points to the element next to it. It is unclear if you want the objects in elements to point to copies of them, anyway it should be pretty easy to modify the code to achieve the latter

This is what happens in your code:

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
}

so nothing gets deleted when myDoc::load() goes out of scope, but you have memory leaks and errors since the pointers aren't pointing to the elements in the elements vector but in the first heap elements you allocated.

That also answers your second question: they're copies.

In order to free your memory automatically, have no leaks and point to the right elements you might do something like

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

No need to delete anything in the destructor since the smart pointers will be automatically destroyed (and memory freed) when the myDoc element gets out of scope. I believe this might be what you wanted to do since the elements are owned by the myDoc class anyway.

Upvotes: 1

Related Questions