How to deal with dynamic allocation when implementing list of objects?
Asked Answered
V

2

6

I had to implement a function that looked like this:

MyList * sum (MyList * l1, MyList * l2) {
    MyList * newlist = new MyList();
    //Adds two objects and place the result in a third new list
    return newlist;
}

The function took two lists and placed the sum of each object into a new list. The MyList class had nodes with pointers to the next variable and the objects inside the list were user defined.

And that got me thinking - how should I deal with the dynamic allocation of memory from the objects and the list itself? Since I had to create memory for each of the objects of the new list.

Is there any way to place the values of the sum of objects in the new list without having to rely on dynamic allocation? Maybe by doing something like this:

Object result(node1->content + node2->content);
Node->content = &result; // will this object be erased when the function ends?

instead of this:

Node->content = new Object(node1->content + node2->content);

How should I deal with the lifetime of the new list created inside of the function in relation to the variable that will hold the memory after the function ends? Can I do something like this when returning the new list?

MyList & sum (MyList * l1, MyList * l2) {
    //Create variable without allocating memory and return it's reference 
}

In short, my main doubt is how to deal with the lifetime of an object that is created inside a function and will be held by other object.

Vortumnus answered 30/8, 2017 at 16:13 Comment(4)
have you considered std::shared_ptr/std::unique_ptr?Hypercatalectic
Use std::list. The std::list automagically manages memory for you.Lessielessing
Uhh, why would anyone insist on that function signature...Emulous
I don't know how to use smart pointers yet. I'll look into it. I already use std::list in my implementations and i'm aware that the recommendations are not to handle pointers when you don't need to. I just wanted to understand the lifecycle of variables inside objects and don't pretend to reimplement std::list. Thanks for the answers.Vortumnus
F
0
Object result(node1->content + node2->content);
Node->content = &result; // will this object be erased when the function ends?

Yes, if result is created inside the function body with the syntax shown above, it will be destroyed when the function ends.

This is the reason why you should use new and dynamic allocation: in this way, your objects are created on the heap (instead of the local function stack), and they "survive" the end of the function in which they are created. And you can pass the returned pointer back to the caller. Of course, the caller has to properly delete the returned pointer, else you end up having memory (or other resource) leaks.

In modern C++, you should use already-defined smart pointer classes, like std::shared_ptr or std::unique_ptr, and your code should almost never use explicit new and delete (unless you are developing some custom highly-optimized data structure, and you need low-level finer-grained control on memory allocations - and, even in this case, the explicit code invoking new and delete should be safely wrapped inside RAII class boundaries).

However, it seems to me that your code is more like a programming exercise, and probably the purpose of this exercise is to learn dynamic memory allocations with explicit new and delete. In fact, in production-quality code, instead of rolling your own list class, you can use an already available standard linked-list class template, like std::list.

Fidole answered 30/8, 2017 at 18:28 Comment(0)
O
2
Node->content = &result; // will this object be erased when the function ends?

Yes, since it's a local variable. As soon as its function terminates, so does result's lifetime.


MyList & sum (MyList * l1, MyList * l2) {
    //Create variable without allocating memory and return it's reference 
}

This will fail too, for similar reasons as the above.


I suggest you use std::shared_ptr or std::unique_ptr. If you wish, read Differences between unique_ptr and shared_ptr.

Outflow answered 30/8, 2017 at 16:37 Comment(0)
F
0
Object result(node1->content + node2->content);
Node->content = &result; // will this object be erased when the function ends?

Yes, if result is created inside the function body with the syntax shown above, it will be destroyed when the function ends.

This is the reason why you should use new and dynamic allocation: in this way, your objects are created on the heap (instead of the local function stack), and they "survive" the end of the function in which they are created. And you can pass the returned pointer back to the caller. Of course, the caller has to properly delete the returned pointer, else you end up having memory (or other resource) leaks.

In modern C++, you should use already-defined smart pointer classes, like std::shared_ptr or std::unique_ptr, and your code should almost never use explicit new and delete (unless you are developing some custom highly-optimized data structure, and you need low-level finer-grained control on memory allocations - and, even in this case, the explicit code invoking new and delete should be safely wrapped inside RAII class boundaries).

However, it seems to me that your code is more like a programming exercise, and probably the purpose of this exercise is to learn dynamic memory allocations with explicit new and delete. In fact, in production-quality code, instead of rolling your own list class, you can use an already available standard linked-list class template, like std::list.

Fidole answered 30/8, 2017 at 18:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.