0

When I am declaring an array on the heap, which method is better? For simplicity and example's sake the private data is made public here.

Should I create a new pointer, modify data, and then

CAT *Family = new CAT[2];

for(int i=0; i<2;i++){
    Family[i].age = i+1;
}

VS

CAT *Family = new CAT[2];
CAT *pCat;


for(int i=0; i<2;i++){
    pCat = new CAT;
    pCat->age = i+1;
    Family[i] = *pCat;
    delete pCat;
}
Quaxton Hale
  • 2,460
  • 5
  • 40
  • 71
  • 1
    The second method seems to have no advantage at all over the first, and is more complicated. – Beta Sep 28 '14 at 04:24
  • Do you have any reason to believe the second method has any advantage at all? – R Sahu Sep 28 '14 at 04:35
  • @RSahu No, I use the first method. But I saw the second in an example. Was just curious. – Quaxton Hale Sep 28 '14 at 04:36
  • However, the second method is useful for polymorphism. Imagine that Family is of class Animal, so that other than CATS can be stored. – Javi Sep 28 '14 at 04:42

4 Answers4

2

It's generally not a good idea to use raw pointers and new directly.

The less of that, the better.

Instead, to create your array on the heap, do this:

std::vector<Cat> cats( 2 );
for( int i = 0; i < int( cats.size() ); ++i ){
    cats[i].age = i+1;
}

or alternatively, this:

std::vector<Cat> cats;
for( int i = 0; i < 2; ++i ){
    cats.emplace_back( i+1 );
}

The direct use of raw arrays and new indicates a C programmer or incompetent, since std::vector is in the C++ standard library precisely for this purpose, taking care of correct memory management.


Note also that ALL UPPERCASE names are a convention used for macros. The idea is to minimize the chance of name collisions and inadvertent text substitution. When you use such names for other things, you instead increase the chance of name collisions and inadvertent text substitution, not to mention that many programmers read all uppercase as shouting, extra strong emphasis.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
1

The first approach has a definite advantage in terms of number of times the Constructor is called. For your trivial example, its fine. However, assume a class that does heavy resource allocation in c'tor and frees them in d'tor. The second approach would call these c'tors and d'tor 2 times extra which is a heavy penalty. #include using namespace std;

class CAT{
public:
 CAT(){ cout<<"c'tor called"<<endl;}
 int age;
 ~CAT(){ cout<<"d'tor called"<<endl;}
};

main(){
  CAT *Family= new CAT[2];
  CAT *pCat;

  for(int i=0; i<2;i++){
    pCat = new CAT;
    pCat->age = i+1;
    Family[i] = *pCat;
    delete pCat;
  } 
}

Run it 

$./a.out 
c'tor called
c'tor called
c'tor called
d'tor called
c'tor called
d'tor called
sanjayk79
  • 542
  • 3
  • 15
0

Your second implementation is going allocate more variables on the stack and is going to require more complex assembly code (I remember having to generate assembly code for the above code for a C style language, and it get's harry!). For bonus points, if you're looking for optimizations, I suggest you use a pre-increment in your for loop ;)

Community
  • 1
  • 1
Devarsh Desai
  • 5,984
  • 3
  • 19
  • 21
0

I don't see any advantage to the firs method if you are trying to create an array of objects. However, the second method would be necessary if you are trying to create an array of pointers, which could point to different concrete types.

struct A
{
   virtual ~A() {}
};

struct B : A
{
   int data;
}

struct C : A
{
   double data;
}


int main()
{
   A* array[20];

   // Get half of the array filled with B*.
   for (int i = 0; i < 10; ++i )
   {
      B* b = new B;
      b.data = i*10;
      array[i] = b;
   }

   // Get the other half of the array filled with C*.
   for (int i = 10; i < 20; ++i )
   {
      C* c = new C;
      c.data = i*1.5;
      array[i] = c;
   }

   // Delete the objects.
   for (int i = 0; i < 20; ++i )
   {
      delete array[i];
   }

   return 0;
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270