views:

113

answers:

6

In C++, ff I have a class that needs to hold a member which could be dynamically allocated and used as a pointer, or not, like this:

class A {
    type a;
};

or

class A {
    A();
    ~A();
    type* a;
};

and in the constructor:

A::A {
    a = new type();
}

and destructor:

A::~A {
    delete a;
}

are there any advantages or disadvantages to either one, aside from the dynamic one requiring more code? Do they behave differently (aside from the pointer having to be dereferenced) or is one slower than the other? Which one should I use?

A: 

With the pointer you have more control, but also more responsibilities. You have more control in the sense that you can decide the lifetime of the object more precisely, while without the pointer the lifetime is essentially equal to the lifetime of the containing object. Also, with the pointer the member could actually be an instance of a subclass of the pointer type.

Performance-wise, using the pointer does mean more memory usage, more memory fragmentation, and dereferencing does take amount of time. For all but the most performance critical code none of this is really worth worrying about, however.

Laurence Gonsalves
A: 

The main difference is that the pointer can potentially point somewhere else.

edit

Laurence's answer isn't wrong, but it's a bit general. In specific, dynamic allocation is going to be slightly slower. Dereferencing through the pointer is likewise going to be very slightly slower. Again, this is not a lot of speed loss, and the flexibility it buys may well be very much worth it.

Steven Sudit
A: 

The main difference is that if you don't use a pointer, the memory for the inner member will be allocated as a part of the memory allocated for the containing object. If you use new, you will get memory in separate chunks (you already seem to have proper creation and destruction of the referenced object down)

Matti Virkkunen
A: 

You need to understand the implications of default copy constructor and copy assignment operators when using raw pointers. The raw pointer gets copied in both the cases. In other words, you will end up having multiple objects (or raw pointers) pointing to the same memory location. Therefore, your destructor written as is above will attempt to delete the same memory multiple times.

naivnomore
+5  A: 

There are several differences:

  1. The size of every member must be known when you're defining a class. This means you must include your type header, and you can't just use a forward-declaration as you would with a pointer member (since the size of all pointers is known). This has implications for #include clutter and compile times for large projects.

  2. The memory for the data member is part of the enclosing class instance, so it will be allocated at the same time, in the same place, as all the other class members (whether on the stack or the heap). This has implications for data locality - having everything in the same place could potentially lead to better cache utilization, etc. Stack allocation will likely be a tad faster than heap allocation. Declaring too many huge object instances could blow your stack quicker.

  3. The pointer type is trickier to manage - since it doesn't automatically get allocated or destroyed along with the class, you need to make sure to do that yourself. This becomes tricky with multiple pointer members - if you're newing all of them in the constructor, and halfway through the process there's an exception, the destructor doesn't get called and you have a memory leak. It's better to assign pointer variables to a "smart pointer" container (like std::auto_ptr) immediately, this way the cleanup gets handled automatically (and you don't need to worry about deleteing them in the destructor, often saving you from writing one at all). Also, any time you're handling resources manually you need to worry about copy constructors and assignment operators.

tzaman
Adding smart-pointer containers-includes (stl/boost) to your project generally increases your compile time a lot more than including your own header files. Stack allocation, which are considered cheap, are a lot faster than heap allocations (which are considered expensive).Why would you need to worry about copy constructors and assignment operators if you're handling resources manually? Make sure to keep pointers to them instead of copying them. (simply declare copy/assignment as private and you'll never make the mistake of doing wrong).
Simon
A: 

If the member variable should live beyond the lifetime of the object, or if its ownership should be transferred to another object, then the member should be dynamically (heap) allocated using "new". If it is not, then it is often the best choice to make it a direct member of the class in order to simplify code and lessen the burden on the memory-allocator. Memory allocation is expensive.

Simon