1

I am often seeing these kinds of declarations:

class A
{
private:
    int a;
    int b;
public:
    // Ctor + Dtor + methods 
};

class B
{
private:
    int a;
    int b;
public:
    // Ctor + Dtor + methods
};

class C
{
private:
    A* aClass;
    B* bClass;
    // Other members.
public:
    // Ctor + Dtor + methods
};

aClass and bClass are dynamically allocated with the new operator.

Assumption

A lot of people tend to use the heap when there is apparently no reason to. Dynamically allocating A and B classes will decrease the size of the C object on the stack. However, the new operator is "costly" (execution time), and suppose we have getters and setters for all the variables contained in A and B, setting or getting a member of A and/or B will lead to some extra computation in order to access A or B (dereference A or B and then proceed to an operation).

Here are my questions:

  • Would it be better to write the following?

    class C
    {
    private:
        A aClass; 
        B bClass;
        // ....
    }
    
  • Can proceeding this way with large objects lead to a stack overflow?

  • Is the compiler able to proceed to some optimization if he does not know the "true type" of A* and B*?

Edit

I forgot to mention that C is a composition, in both cases (thanks C.LECLERC). The first case is used to realize a composition.

trincot
  • 317,000
  • 35
  • 244
  • 286
Papipone
  • 1,083
  • 3
  • 20
  • 39
  • 6
    It depends. "Saving stack space" is not the only reason that one might choose to use dynamic allocation / pointers. – Oliver Charlesworth Sep 09 '16 at 15:12
  • 2
    If `A` and `B` are bases for a polymorphic class hierarchies then you need a pointer type if you want virtual mechanics. – NathanOliver Sep 09 '16 at 15:14
  • `aClass` and `bClass` are just pointers when or if the actual object is created could depend on a number of circumstances – deW1 Sep 09 '16 at 15:15
  • Your code doesn't use the heap anywhere. Also, do you really need all those member variables to illustrate your point? – juanchopanza Sep 09 '16 at 15:15
  • 1
    @NathanOliver: or A and B don't have a default constructor, although it could be defined by parent constructor. If A and B don't need polymorphism, then values are better than pointers, to save copy/delete/memory leak future issues. – Jean-François Fabre Sep 09 '16 at 15:15
  • @juanchopanza I suppose that A* and B* are dynamically allocated with new. – Papipone Sep 09 '16 at 15:18
  • You could put that in your question (relevant) and remove your zillion data members (irrelevant.) – juanchopanza Sep 09 '16 at 15:20
  • 1
    The first code is an aggregation relationship implementation and the second one is a composition relationship implementation. Thoses too relationships leads to different behaviors (object lifetime & co...). Take a look at UML relationships. – C.LECLERC Sep 09 '16 at 15:24
  • 1
    http://stackoverflow.com/questions/599308/proper-stack-and-heap-usage-in-c – HazemGomaa Sep 09 '16 at 15:45
  • @HAG yes I know the differences. – Papipone Sep 09 '16 at 15:47
  • 1
    so, use the stack if you "can", and use the heap if you need to ... it really depends on what you are trying to do .. – HazemGomaa Sep 09 '16 at 15:54
  • 1
    IMO you're better off not thinking about "stack" and "heap" , and instead use whatever sort of allocation matches the lifetime you want for the object. If the `A` and `B` are supposed to begin when a `C` begins and die when it dies, they should be members (not pointers). If you need a `C` to attach to existing instances of `A` and `B` then use a pointer of some sort. – M.M Sep 10 '16 at 05:55

1 Answers1

0

Okay what if you made a Deck and a card class. Look Below

namespace game{

enum Rank{ACE=1,TWO,THREE,FOUR,FIVE,SIX,SEVEN,
               EIGHT,NINE,TEN,JACK,KING,QUEEN};

enum Suit{SPADE,DIAMOND,CLUB,HEART};

Class Card{
 public:
    Card(){
    suit = HEART;
    rank = ACE;
    }

    Card(int s, int r){
      suit = static_cast<Suit>(s);
      rank = static_cast<Rank>(r);
    }
 private:
    Rank rank;
    Suit suit;
};

Class Deck{
      public:
         Deck(int count){
              card = new Card[count];
        }
   // You would need a copy constructor of course but im lazy

       ~Deck() { delete [] card; } // Manually deallocate

         private:
          Card *card;
         };
     }

Now if we went over to main and made a new deck, this deck would have the amount of the cards the user typed inside it. This is just an example that I would use, and say we made 52 blank cards, lets have a function in the deck that generates a deck, using another method from card that makes random cards, or perhaps a standard deck.

The thing you are asking though is a bit odd, becuase you defined the A and B class so what is a "true type"

Of course some things run faster or slower than others, like using a linear or binary search on an array, one is obviously faster.

Study the relationships of the memory and such when you allocate these objects.

Also look at composition, aggregation and more relationships closely.

As for the stack overflow, are you working on an embedded system, or making one million objects, otherwise you should be fine!

Bayleef
  • 185
  • 2
  • 10