Memory allocation vs stack allocation

Hi,

i am not expert of C++, so i have this general question about C++. What is better, mem alloc or stack alloc?

That means:

auto o = Foo::Foo();

vs

auto o = new Foo();

?

I guess first is stack alloc, and second mem alloc. First uses dot notation, second uses arrow. (First returns the object(?), while the second returns the pointer to object)

I know, that for example deleting of mem object is like

delete o;

Not sure how is it with stack object.

Is there any difference in general? What is more recommended? Is it bad idea to return object from stack eg in custom class constructor? For example because, if there will be many objects created like this, there can be some stack overflow or so? Or any disadvantage too may be? I am not sure.

Eg like this:

TurnManager TurnManager::create(int turnTime)
{
auto tm = TurnManager::TurnManager();
return tm;
}

Thx,

L.

You cannot return a stack allocated object. The object will be destroyed and you will have a pointer or reference to something that is no longer valid.

Also, the code above actually allocates 2 objects. The first Foo::Foo() creates a temporary on the stack, and then it gets assigned to o by way of a copy constructor. The correct way to allocate an object on the stack is simply Foo o;

You can also allocate stack space using alloca for example…

void* some_space = alloca(1024);

Which allocates 1K of memory on the stack. You do not need to free this memory as it will automatically disappear when the function exits scope. You can pass this memory and the object in the example above to functions you call, you just cannot return it from the current function as it will be destroyed.

Note that in your create example above, you are returning a copy of the stack variable, not the variable itself. In this case it is equivalent to just returning return TurnManager();

A better way would be this…

TurnManager* TurnManager::create()
{
    auto tm = new TurnManager;
    tm->autorelease();
    return tm;
}

In this case, TurnManager inherits from Ref, which allows you to autorelease it, which will prevent a memory leak if you do not explicitly retain it. This is the memory model that Cocos2d-x adheres to.

Justin

1 Like

Wow, that shocked me a bit! For example:

Also, the code above actually allocates 2 objects. The first Foo::Foo() creates a temporary on the stack, and then it gets assigned to o by way of a copy constructor.

Yes i was thinking about this:

The correct way to allocate an object on the stack is simply Foo o;

Just like one minute back, that it could be also possibility. But you learned me, that it is only correct in case of stack allocation.

I don’t want to alloc exact bytes, because that’s too much low level, i mean with additional problems like, like correct size of alloc etc.

Ok i will rather work with mem alloc then, and with pointers.

Is

auto tm = new TurnManager;

same as

auto tm = new TurnManager();

? … and

tm->autorelease();

Makes it it autoreleasing object? Ah, now i see i must make it also inherit from Ref, as you say.

Ok that’s great. Yes i knew a bit about auto releasing, but i didn’t know how to set up object to be AR. So that’s great you also pointed this.

Valuable informations in your reply, great. Thank you! I knew i should ask about that :).

But, to the auto releasing of stack objects (Yes i read that those objects are auto released when the scope executes, althought i thought in case of return etc, that will be another case).

I wanted say, that i have for example vector of Objects eg.

std::vector < Foo > _x;

then i do this:

{
auto y = Foo::Foo();
_x.push _back(y);
}

And the y Foo object is accesible, even if the scope finished, and it is stack object :), i mean accesible from vector like
_x[0]. and there is no null pointer etc, as you said for case of custom constructor.

Thanks again!

Lukas

Not, they are different. The first one is (inits to) indeterminate and the second one inits to the default values or zero. But all this depends on the data types and compilers.
There is a valuable post here, without going into to much detail:

Cause the parameter for the std::vector push_back method uses copy by value.

The content of val is copied (or moved) to the new element.

1 Like

Ah… ok… great ! Thank you very much… :blush: Ps, i am starring how much detail things there is in C++ :smile:

And you barely scratched the surface :smile:

That’s why people are “scared” of using C/C++: they are afraid of shooting themselves into the foot to often.

If you want to learn/know every ins and outs of C++, you should dig through the C++ standard and/or the standard books/bibles about the C++ language.

1 Like

A little more detail on this…

The first will call a constructor if one has been specified.

    struct Foo1
    {
        float x;
    };

    struct Foo2
    {
        float x;
        Foo2()
            : x(0)
        {}
    }

Foo1 which declares no constructor will have x be indeterminate, whereas Foo2 will call the constructor and set x to 0.

When you use the parentheses and call Foo() explicitly, you are forcing the compiler to generate a call to the default constructor, even though you have not declared one. In this case the compiler will generate code that usually 0’s the memory for you.

Where this can be a pain or not desirable is when you need a struct (or class) to be super fast to create. For example if you are writing a particle system that creates and destroys 1000’s of particles per second, then you don’t want them to default the memory to anything, since you are going to be setting the particle data up yourself anyway. So if you create a temporary you don’t care if it’s initialized or not.

2 Likes

Aha! Great example with particles. Thank you…

I will need now some time to store all these info in my head. It’s a bit too much info at once :smile:

But i see you are really C++ expert :smile:

L.