1

I have spent a couple hours looking for discusion on this both in some good C++ books as well as here on stack overflow, and while I have seen quite a number of questions regarding the "heap vs stack" question, I'm looking more specifically for an understanding of the use of pointers or not in creating object members of a class, i.e. with composition.

For example:

class A{
B c;
}

vs.

class A{
B*c;
}

In the first example, this is not really a "stack" allocation, rather an allocation in the "static storage area," which is a different thing, so discussions of stack vs heap don't apply, I think.

What's not clear to me are the pros and cons of either. It seems like most code I read is using the second option, but why?

It's possible I don't know the proper terminology of these techniques to search this site properly, or else there simply haven't been questions on this. If there are indeed answers pertaining to this elsewhere, by all means let me know how to find them, but nearly everything seems to be more about stack vs heap in the context of a local variable, and I think I have a handle on that okay.

johnbakers
  • 24,158
  • 24
  • 130
  • 258
  • Most code is using the second? That's very bad. – chris Feb 02 '13 at 09:06
  • That has been my experience. What's the main reason to do one or the other? – johnbakers Feb 02 '13 at 09:06
  • Because pointers, especially raw ones, are very often unnecessary and just complicate things. – chris Feb 02 '13 at 09:07
  • I agree, hence my question. Does it have anything to do with the complexity or size of an object, i.e. a "big" object should be dealt with using pointers only? – johnbakers Feb 02 '13 at 09:09
  • C++11 kind of screws over the big object argument with move semantics :) – chris Feb 02 '13 at 09:12
  • The second method supports forward declarations (ie declare `B` before `A` but define later). It lets the header files require less others. Plus both of them will be on the heap, it's just that the first example will have `sizeof(A) >= sizeof(B)` as `B` is contained by `A` – user1520427 Feb 02 '13 at 09:16

2 Answers2

1

The reason why people use the 2nd option is this:

class A { B b;}; // error, order of classes wrong
class B { }; 

This simple feature of C++ makes it difficult to build working system with the B b; style. You have to put all related classes to same file and reorder the classes to exactly correct order.

Also inheritance does some magic with the order too:

class A : public B { }; // error, order of classes wrong
class B { };

So using inheritance and B b; together is fixing the order of classes completely and large number of data members will be nightmare. (note that types like float and int does not have the order problem - and it's possible to do it correctly for classes too)

tp1
  • 1,197
  • 10
  • 17
  • Not sure how this really applies if your member class is defined in a separate file, since that file will be included and thus the compiler will see it before you make that class a member object anyway. – johnbakers Feb 02 '13 at 09:11
  • @Sebby johanns: #includes has the problem that the order is decided several times -- once for every translation unit. People have problems deciding the order correctly just once, much less several times. This is why they need to be in same file, so that there is just one order, and not many of them. – tp1 Feb 02 '13 at 09:13
  • To simplify the examples you can come up with, just think of a linked list. Good catch with the incomplete type reasoning, though. That's a valid reason. – chris Feb 02 '13 at 09:14
  • in addition i found this answer: http://stackoverflow.com/questions/8589739/pointer-vs-non-pointer-members-of-a-class – johnbakers Feb 02 '13 at 09:25
0

Another reason to have a pointer to an object as a member of your class is if you actually need it to point to something and you want the pointed object to change frequently. For example imagine a class that keeps a pointer to the active window in some system or framework (totally imaginary). The memory of the object pointed to by activeWindow below will be allocated elsewhere and the pointed object itself will change frequently.

class Monitor
{
...
Window* activeWindow
...
}

On the other hand having pointers for everything and using the new operator (or malloc()in C) to allocate memory manually tends to be slow because allocating memory on the heap is slower than memory on the stack and also requires manual freeing later. So it should be avoided if possible.

If you can do away with having the object in the storage area of the class and not allocate it on the heap then do so.

class foo
{
B c;
};

is certainly better than

class foo
{
public:
 foo()
 {
   this->c = new B();
 }
 ~foo()
 {
   delete this->c;
 }

private:
B* c
};

But then again it all depends on the nature of class B

Lefteris
  • 3,196
  • 5
  • 31
  • 52
  • I think that both examples, with or without a pointer, allocate to the heap, as I've read elsewhere and is explained in the comments to this question and its other answer. The allocation speed isn't really the issue here, since neither is allocated to the stack. – johnbakers Feb 02 '13 at 09:33
  • @Sebby Johanns In my opinion it's not so much a matter of speed as much as it is of manual managing of memory. As far as both of them allocating to the heap that's strange. I will search around to make sure. Will definitely learn something new if you are right :) – Lefteris Feb 02 '13 at 09:37
  • since both must reside indefinitely, neither can go to the stack. – johnbakers Feb 02 '13 at 09:38
  • @SebbyJohanns hmm yeah you are right I think. I am just so used to calling anything that manually allocates memory, allocation on the heap that I got carried away here. I guess the matter remains though. How much you want to deal with manual memory allocation and also what is the nature of the classes you deal with. In C++ try to follow RAII as much as possible (http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization) – Lefteris Feb 02 '13 at 09:47