Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I really have never understood it at all. I can do it, but I just don't get why I would want to.

For instance, I was programming a game yesterday, and I set up an array of pointers to dynamically allocated little enemies in the game, then passed it to a function which updates their positions.

When I ran the game, I got one of those nondescript assertion errors, something about a memory block not existing, I don't know. It was a run-time error, so it didn't say where the problem was. So I just said screw it and rewrote it with static instantiation, i.e.:

while(n<4)
{
Enemy tempEnemy = Enemy(3, 4);
enemyVector.push_back(tempEnemy);
n++;
}
updatePositions(&enemyVector);

And it immediately worked perfectly.

Now sure, some of you may be thinking something to the effect of "Maybe if you knew what you were doing," or perhaps "n00b can't use pointers L0L," but frankly, you really can't deny that they make things way overcomplicated, hence most modern languages have done away with them entirely.

But please-- someone -- What IS the point of dynamic allocation? What advantage does it afford? Why would I ever not do what I just did in the above example?

share|improve this question
2  
with your above std::vector, the sizeof(Enemy) is fixed and can only contain one type. With polymorphism and pointers, you can store objects of different type in the container and each object can have different sizeof(T) since the std::vector<Enemy*> will only contain addresses instead of the whole data. –  tp1 Jun 9 '12 at 17:19
    
Interesting; I didn't think of that. So my above example would not allow enemyVector.push_back(subclassOfEnemy)? –  Aerovistae Jun 9 '12 at 17:28
1  
No it wouldn't. In fact, you'd experience slicing (en.wikipedia.org/wiki/Object_slicing) –  Chase Meadors Jun 9 '12 at 17:57
    
Of course you can solve the slicing problem by using a container designed to hold pointers and manage them like objects (so you don't need to change your code). boost::ptr_vector<Enemy> enemyVector; enemyVector.push_back(new subclassOfEnemy); Worrks just like the above and handles pointers for you. –  Loki Astari Jun 9 '12 at 18:07
2  
Modern languages haven't done away with pointers at all. They just restrict their usage to patterns that the language designers considered safe. –  tdammers Jun 9 '12 at 19:50

5 Answers 5

up vote 20 down vote accepted

First off, you are using dynamic allocation. You just don't handle raw pointers yourself. But std::vector, as nearly all other useful data structures, internally allocates memory dynamically. This is because your only alternatives are: Static allocation (far too limited, you have to know the size at compile time) and stack allocation (far too limited, a few megabytes at most and it's deallocated as soon as the allocating function returns). Dynamic gives you the largest amount of memory and the most freedom in how you use it. A pointer or reference also abstracts over the size of what's allocated - on the stack, you have to know at compile time (or use alloca to allocate manually, but then you need even more care and still get a pointer).

Second, many C++ programmers will agree that raw pointers are not very useful most of the time, precisely due to the complexity and error-proneness you cite. You need them under the hood, and you should absolutely be able to use them, but you shouldn't do it in 99% of all code in the interest of sanity, correctness, programmer performance, exception safety, memory leak avoidance, etc. Your alternatives are some combination of containers (std::vector is just the tip of the iceberg), smart pointers, other forms of RAII, plain old stack allocation whenever you can get away with it, and references.

Also note that there is a difference between pointers (and other kinds of indirection) and dynamic allocation. Pointers (raw and smart, as well as references) afford you (as a commenter pointed out) polymorphism, regardless of how the pointed-to object is allocated. You will have to wrap your head around them, around references, around smart pointers, and about issues like ownership that follow suit, regardless of what/where/how you allocate.

share|improve this answer
    
The part is still don't get is "(far too limited, you have to know the size at compile time)"...what's to stop me changing the value of the loop delimiter variable? I can add as many tempEnemies to that vector as I want, depending how long I run the loop. –  Aerovistae Jun 9 '12 at 18:07
    
@Aerovistae: I think the point is you should not normally be using pointers directly. You should be using containers and smart pointers to manage your pointers. BUT every now and then you need to write a smart-pointer/container (like std::vector) then you need to use pointers directly so you can write them efficiently. –  Loki Astari Jun 9 '12 at 18:23
2  
@Aerovistae: Yup--but there's still dynamic allocation going on under the hood. If you look at the source for vector::push_back, you'll see that there's a call to new somewhere in there (or in something it calls). Static allocation only happens when you do something like int a[N] and that N must be known at compile time. –  Matt Krause Jun 9 '12 at 18:49
    
@Aerovistae Static allocation (which is what the quoted section refers to) happens with things like global and static variables, static members, and the like. What Matt Krause cites is not a prime example, because alloca and variable-length arrays (C99 and extensions) gives you the same with a non-constant N. And again, the vector uses dynamic allocation, so you do use dynamic allocation. –  delnan Jun 9 '12 at 20:25

Well, you're way wrong about modern languages not using pointers. They call them different things, but they're still pointers under the hood. And they do not even get rid of stack-allocations either, look at .NET for example and see the difference between reference types and value types.

However that's as makes no difference to you. Your problem is that you don;t quite understand what happens with your allocations.

Computers work with a huge lump of memory that they split into 2 groups, the heap and the stack. The stack is used for temporarily passing data between function calls, the heap is a more 'global' storage space for objects. In C++ you get the stack for free by allocating as you've done - Enemy e; is a stack allocation. To use the heap you must create the object and then keep track of where it was allocated yourself, usually by using a pointer. So Enemy* e = new Enemy(); will allocate an Enemy-sized object on the heap, but will be a pointer to that object, no that object itself. Note that e itself is allocated on the stack (every variable has to be stored somewhere after all).

Now thing what happens when you call a function - you know about copy by value and copy by reference? If you've allocated your object on the stack you will get a copy of the object when you call a function, but if you've allocated it on the heap, when you pass the pointer, you will get a copy of the pointer (which, of course, still points to the same object on the heap).

I guess if you're used to Java or .NET's way of handling heap-based objects for you, then the closest you'll get with C++ is to use the smart pointers, shared_ptr<> is probably what you want. Use these instead of raw pointers, or stack objects and you'll be a lot happier. The bonus over GC languages is that you'll also get instant deallocation of them once no-one is using the object anymore (so you can put your enemy death throes routines in the destructor and let the system automatically call it when the enemy is deleted)

share|improve this answer

Aerovistae, you really need to learn what dynamic allocation is :) also you should be able to debug that kind of problems that you got.

In short, from looking at the code, you put your Enemies into a vector by value. That means that vector may copy them and move the objects around. What that means that if you start adding more Enemies, some Enemies will be copied by value, and some destructors called. Depending on how your Enemies written, this could be some fuck-up. At the same time, with passing by value you can't be sure about object location anymore: vector may reallocate the object and if there is something else in the code holds pointers to these objects these pointers will be invalidated.

In short, that kind of stuff should be absolutely clear to you, then your wouldn't ask questions like you did.

share|improve this answer

delnan provided a good explanation of what dynamic allocation is. +1 to that.

The only thing I want to add is that you use dynamic allocation when you need to. If you have small fixed size of objects, sure allocating them statically is good enough for now. If you have a need for short lived objects within a single function, sure local objects on the stack are great.

Only allocate objects dynamically when the other methods are not good enough. Don't use it just because the language allows it. Sooner or later, you will have a need.

Same goes with C++ templates. I have seen way too many people start plopping templates all over the place just because. Then same people complain how C++ is too convoluted and complicated. C++ has many advanced features, but it is up to the developer to determine when and where to use those features. But when there's no other alternatives, dynamic allocation (and templates) will allow you to do things which otherwise would've been impossible.

share|improve this answer

The main difference between C++ and a language like Java, is that in Java, you make a statement like

MyObject b = new MyObject(...);
myArrayOfObjects.add(b);

Objects ARE references. This abstraction has proven to be very powerful in higher level languages. Objects are allocated on the heap and reference counted, taking away our responsibility to de-allocate that memory. The garbage collector simply can tell when an object has no references left to it, and sweeps it clean.

The fact of the matter is, C++ is not AS higher level. An advantage of C++ is that you CAN drop down to very manual memory management to get better performance or tweak certain performance intensive areas of your code.

In C++, if your object is going to be a member of a class, or otherwise passed around, stored, and needed by other classes, etc., you should use a pointer.

MyObject *myClassMemberVariable

Now, there are propenents in C++ that advocate never using raw pointers like this. Libraries like boost and even the standard library make classes like smart pointers and other things that attempt to implement somewhat automatic memory management of resources, by "wrapping" raw pointers, providing different schemes for them to manage the memory.

It all comes down to you having to make your own decision about when to use pointers and how to manage memory. This is mainly what makes C++ harder than other languages (that among... other things). However, it does have its use and its advantages to the projects that use it.

share|improve this answer
1  
The term reference. Means different things in C++ and Java. So tying to explain things using that term is counter productive. C++ also has referenced counted dynamically allocated objects (you just have to decide to use them std::shared_ptr (or boost::shared_ptr). C++ is just as high level as Java it just allows you to also go low level. And the loss of RAII makes Java much more verbose (and thus harder to write correctly (see Does C++ support 'finally' blocks?). –  Loki Astari Jun 9 '12 at 18:14
    
So its swings/roundabouts on which is harder to use correctly. The difference C++ will blow your head off before crashing while Java will whimper in the corner not doing anything (but not hurting you). –  Loki Astari Jun 9 '12 at 18:26
    
"C++ is just as high level as Java it just allows you to also go low level.": I disagree. Being high level means (1) to provide an abstraction (which C++ does) and (2) to hide its implementation (which C++, by making the lower levels accessible, does not). In other words C++ provides certain high-level constructs but does not (always) prevent you from messing them up. According to my intuition, a language that also enforces the correct use of its abstractions is higher level (its abstractions are less fragile). –  Giorgio Dec 12 '12 at 15:51

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.