views:

105

answers:

4

Let's say I have a class that allocates some arbitrary member data. There are two common ways that I have seen used (I know that there are others):

class A
{
    public:
        A();
        ~A();

        //Accessors...
    private:
        B *mB;
}

A::A()
{
    mB = new B();
}

A::~A()
{
    delete B;
}

Versus...

class A
{
    public:
        //Accessors...
    private:
        B mB;
}

Assume that A itself will be allocated on the heap by consumer code.

In the general case, which method is preferred? I realize that specific situations really encourage one way or the other, but in absence of those demands, is one way preferred? What are the tradeoffs?

+9  A: 

The second is the preferred route. Do not use new / delete unless you specifically need a variable to be on the heap or have a lifetime longer than it's container. C++ value types are easier to manage and have less error cases to worry about IMHO

JaredPar
A: 

In general, prefer direct composition (the second choice). In that case there is no chance of leaking memory and the object is fully located in a contiguous memory block, allowing better cache locality.

You might use the first option if you're implementing a PIMPL, or you have a need to use one of several possible class types (via inheritance). In that case definitely use a smart pointer (boost::shared_ptr for example) to manage the memory for you.

Mark B
+4  A: 

It depends.

In general, If a B is large and unwieldy then it's easier to pass around a pointer to the B than the B itself. So if the B will often be disassociated from the A (f'rinstance if your A's swap B's) then the first way is better.

Using a pointer can also reduce dependencies. If you do it right, A.hh can get by without specifiying what a B is or does (i.e. A.h need not #include "B.hh") so that things that depend on A.hh won't necessarily depend on B.hh.

The price of using pointers is an extra layer of machinery and the dangers of things like lost objects, double-deletion and the dereferencing of uninitialized pointers, so it shouldn't be used unless it actually gives a benefit in your situation. Some people fall in love with pointer techniques and use them everywhere; if they want to improve as programmers they have to grow out of it.

Beta
A: 

It depends, mainly, on what you are looking for.

For simplicity's sake: don't use a pointer. Therefore the second choice.

It's easier to manage (no need to worry about memory management, deep copying, deep constness, etc...).

However you might need dynamically allocated attributes sometimes:

  • if you need polymorphism (otherwise you have a truncation)
  • if you want to cut down your dependencies (in the header file) --> see PIMPL here

Even in this case though, hand over the responsibility to a smart manager (smart pointer, dedicated pimpl class, etc...)

Matthieu M.