Dynamic Memory

I have a quick question about dynamic memory. Some say that one purpose of dynamic memory is to let data exist even after the underlying scope that created it has terminated. However, this does not make sense. For example, let's say I have a function foo() and I create a pointer to a block of dynamic memory. The pointer will be destroyed after foo() ends and foo()'s stack frame is cleared. Although the dynamic memory still exists, there is no way of accessing it because the pointer has been destroyed! Therefore, how can you say that using dynamic memory lets you use data longer than the function that created it??????

Last edited on
Well, what you describe doesn't just apply to dynamic memory. Let's say you have a function to calculate the area of a circle.
1
2
3
4
void calculate_area(double radius)
{
    double area = 3.141592654 * radius * radius;
}

How can you use the result of the calculation longer than the function that created it??????
Last edited on
Umm. Wouldnt you just return the value of "area"?

Would the same principle apply to pointers pointing to dynamic memory: just return a " copy" of the pointer? Now there will only be one pointer pointing to the dynamic memory ( the temporary pointer created from returning) and the original pointer is destroyed.

Obviously you can't return a reference to the pointer because it will be invalid as the scope that created it has ended.

Is this how it works?
Last edited on
Some say that one purpose of dynamic memory is to let data exist even after the underlying scope that created it has terminated.

As you mentioned, you could return a pointer to the dynamically allocated memory. Then again, if that's the goal then a much cleaner method would be to allocate the memory in the calling function and pass it down as a reference. That way the called function doesn't have to allocate the memory at all.

Put another way, if the goal of a function is to have data that outlives the function, then there are better ways to do it than dynamic allocation.

The much more common reason to allocate memory dynamically is because you don't know how much memory you will need at compile time. What usually happens is that you put some unknown number of items into a collection of some sort (a vector, list, set, etc.). Another example is a string: you usually don't know how big a string will be at compile time. But if you think about it, even the string is just a special type of collection of characters.

A less common example is when you need a local variable that will take up a lot of memory. Local variables are stored on the stack, which is usually much smaller than the heap, so you may find code that dynamically allocates data in a function and then deletes when the function returns, just to avoid putting the data on the stack. Note that it's best to do this with a unique_ptr<> to avoid possible memory leaks.
Thank you. Just to confirm: the only difference between std::shared_ptr<> and std::unique_ptr<> is that shared_ptr has reference counting, correct?
You can have multiple shared_ptr's pointing at memory and the memory gets deleted when the last pointer points away from it. With unique_ptr, it gets deleted as soon as the unique_ptr points away.
The ownership of an object can only be shared with another shared_ptr by copy constructing or copy assigning its value to another shared_ptr. Constructing a new shared_ptr using the raw underlying pointer owned by another shared_ptr leads to undefined behavior.
http://en.cppreference.com/w/cpp/memory/shared_ptr


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <memory>

struct A { /* ... */ };

int main()
{
    {
        std::shared_ptr<A> pa1 = std::make_shared<A>( /* constructor args */ ) ;

        std::shared_ptr<A> pa2 = pa1 ; // fine, shared ownership (pa2 is a copy of pa1)
    }

    {
        A* pa = new A( /* constructor args */ ) ;

        std::shared_ptr<A> pa1(pa) ;

        std::shared_ptr<A> pa2(pa) ; // *** error: ownership is not shared.
                                     // *** engenders undefined behaviour 
    }

    {
        std::shared_ptr<A> pa1 = std::make_shared<A>( /* constructor args */ ) ;

        std::shared_ptr<A> pa2( pa1.get() ) ; // *** error: ownership is not shared.
                                              // *** engenders undefined behaviour 
    }

}
Topic archived. No new replies allowed.