tags:

views:

920

answers:

4

Is it considered bad manners/bad practice to explicitly place object members on the heap (via new)? I would think you might want to allow the client to choose the memory region to instantiate the object. I know there might be a situation where heap members might be acceptable. If you know a situation could you describe it please?

+9  A: 

If you have a class that's designed for copy semantics and you're allocating/deallocating a bunch of memory unnecessarily, I could see this being bad practice. In general, though, it's not. There are a lot of classes that can make use of heap storage. Just make sure you're free of memory leaks (deallocate things in the destructor, reference count, etc.) and you're fine.

If you want more flexibility, consider letting your user specify an Allocator. I'll explain.

Certain classes, e.g. std::vector, string, map, etc. need heap storage for the data structures they represent. It's not considered bad manners; when you have an automatically allocated vector, the user is expected to know that a buffer is allocated when the vector constructor gets called:

void foo() {
    // user of vector knows a buffer that can hold at least 10 ints
    // gets allocated here.
    std::vector<int> foo(10);  
}

Likewise, for std::string, you know there's an internal, heap-allocated char*. Whether there's one per string instance is usually up to the STL implementation; often times they're reference counted.

However, for nearly all of the STL classes, users do have a choice of where things are put, in that they can specify an allocator. vector is defined kind of like this:

template <typename T, typename Alloc = DefaultAllocator<T> >
class vector {
    // etc.
};

Internally, vector uses Alloc (which defaults to whatever the default allocator is for T) to allocate the buffer and other heap storage it may need. If users doesn't like the default allocation strategy, they can specify one of their own:

vector<int, MyCustomAllocator> foo(10);

Now when the constructor allocates, it will use a MyCustomAllocator instead of the default. Here are some details on writing your own STL allocator.

If you're worried that it might be "bad manners" to use the heap for certain storage in your class, you might want to consider giving users of your class an option like this so that they can specify how things are to be allocated if your default strategy doesn't fit their needs.

tgamblin
I would vote you up, but don't have the rep. So far this is a great answer, thank you.
bluehavana
This answer and the answer from Matt Davis both deserve to be accepted. Since no Rep is gained from acceptance, lets just call them both great answers. Thank you very much.
bluehavana
A: 

hmm, I don't really understand your question.

If you have a class :

class MyOtherClass;
class MyClass
{
  MyOtherClass* m_pStruct;
};

Then, the client of MyClass does not have a real choice on how m_pStruct will be allocated.

But it will be the client's decision on how the class MyClass will itself be allocated, either on the stack or on the heap:

MyClass* pMyClass = new MyClass;

or

MyClass myClass;
Max
+1  A: 

Where the class puts its members is less important than that the management of them is contained within the class; i.e. clients and subclasses shouldn't have to worry about the object's member variable.

The simplest way to do this would be to make them stack variables. But in some cases, such as if your class has a dynamic data structure like a linked list, it doesn't make sense.

But if you make sure your objects clean up after themeselves, that should be fine for most applications.

JohnMcG
+7  A: 

I don't consider it bad practice at all. There are all sorts of reasons why you might want to explicitly allocate a member variable via new. Here are a few off the top of my head.

  • Say your class has a very large buffer, e.g., 512kb or 1MB. If this buffer is not stored on the heap, your users might potentially exceed the default stack space if they create multiple local variables of your class. In this case, it would make sense to allocate the buffer in your constructor and store it as a pointer.
  • If you are doing any kind of reference counting, you'll need a pointer to keep track of how many objects are actually pointing to your data.
  • If your member variable has a different lifetime than your class, a pointer is the way to go. A perfect example of this is lazy evaluation, where you only pay for the creation of the member if the user asks for it.
  • Although it is not necessarily a direct benefit to your users, compilation time is another reason to use pointers instead of objects. If you put an object in your class, you have to include the header file that defines the object in the header file for your class. If you use a pointer, you can forward declare the class and only include the header file that defines the class in the source files that need it. In large projects, using forward declarations can drastically speed up compilation time by reducing the overall size of your compilation units.

On the flip side, if your users create a lot of instances of your class for use on the stack, it would be advantageous to use objects instead of pointers for your member variables simply because heap allocations/deallocations are slow by comparison. It's more efficient to avoid the heap in this case, taking into account the first bullet above of course.

Matt Davis
If I could accept two answers , I would accept this and tgamblin's. Thank you for all the various situations, they all differ enough to give me a broad, pragmatic view of the problem scope and solutions.
bluehavana