2

I'm confused with the following example taken from cplusplus.com

// pointer to classes example
#include <iostream>
using namespace std;

class CRectangle {
    int width, height;
  public:
    void set_values (int, int);
    int area (void) {return (width * height);}
};

void CRectangle::set_values (int a, int b) {
  width = a;
  height = b;
}

int main () {
  CRectangle a, *b, *c;
  CRectangle * d = new CRectangle[2];
  b= new CRectangle;
  c= &a;
  a.set_values (1,2);
  b->set_values (3,4);
  d->set_values (5,6);
  d[1].set_values (7,8);
  cout << "a area: " << a.area() << endl;
  cout << "*b area: " << b->area() << endl;
  cout << "*c area: " << c->area() << endl;
  cout << "d[0] area: " << d[0].area() << endl;
  cout << "d[1] area: " << d[1].area() << endl;
  delete[] d;
  delete b;
  return 0;
}

I was thinking about why d[0].area() is legal as opposed to d[0]->area() and this lead me to the deceleration of d where CRectangle * d = new CRectangle[2];. Isn't there two levels of indirection so shouldn't d be declared with CRectangle ** d since new returns a pointer and it's a pointer to a pointer since it's an array (hence the []). In other words doesn't **=*[]?

Celeritas
  • 14,489
  • 36
  • 113
  • 194
  • 6
    No, **ARRAYS ARE NOT POINTERS!** – chris Jul 08 '13 at 19:53
  • 2
    Don't use cplusplus.com, use [cppreference](http://en.cppreference.com/w/) – Borgleader Jul 08 '13 at 19:54
  • [Everything you need to know about arrays](http://stackoverflow.com/questions/4810664/how-do-i-use-arrays-in-c) – Praetorian Jul 08 '13 at 19:54
  • Eww, the page does one on dynamically allocating members, but fails to even mention the Rule of Three or RAII. – chris Jul 08 '13 at 19:55
  • @antiduh, Part of the reason I particularly like C# and D. No dumb C compatibility to worry about. – chris Jul 08 '13 at 20:02
  • @antiduh "yet i just assigned an array allocated on the heap to a pointer variable" no, you didn't. There are *pointer to array* s in C++, but the type of the expression `new type[number]` is explicitly a pointer to the initial element of the array as per [expr.new]/5. I agree the syntax doesn't reflect this in an obvious way. – dyp Jul 08 '13 at 20:18

2 Answers2

2

CRectangle * d = new CRectangle[2]; declares d as a pointer to CRectangle and initializes it to point to the first object of an array containing two CRectangle objects. So d[0], has type CRectangle, not a pointer to CRectangle. This is why using the dot operator (.) is legal.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
  • Very pedantic: as an object is a region of storage, I think the phrase *element of an array* is slightly better than *object of an array*. The Standard uses the phrase "initial element" in [expr.new]/5. – dyp Jul 08 '13 at 20:09
  • @DyP Hopefully my current edit better emphasizes that I'm referring to the type of `d[0]` which was my initial intent in using the word "object" in the OO sense. – Code-Apprentice Jul 08 '13 at 20:14
  • You're answer is fine and was fine, I just made a very pedantic remark ;) +1 – dyp Jul 08 '13 at 20:16
1

For:

CRectangle *d = new CRectangle[2];

Is (roughly) equivalent to (never, ever, ever do this; just use new):

CRectangle *d = (CRectangle*)malloc(2*sizeof(CRectangle));
... plus some default construction ...

d is a pointer. d[0] is not a pointer, it is the value at the array index 0.

d[n] is shorthand for *(d + n) which is the value (hence the dereference *) at location 'n' in the array d. The return value of new CRectangle[2] is CRectangle*.

Arrays are stored in memory like:

       d[0] [1] [2] [3] [4] [5] [6] [7] ...
Value    A   B   C   D   E   F   G   H  ... 
offset:  0  +1  +2  +3  +4  +5  ( x sizeof(CRectangle) of course)... 
George Mitchell
  • 1,158
  • 2
  • 11
  • 24
  • Except I believe that `malloc` is UB. – chris Jul 08 '13 at 20:03
  • new is equivalent to malloc and a constructor call -- In this case, the default constructor. – Joel Jul 08 '13 at 20:04
  • @Joel, But you can't `malloc` a non-POD type (or can, but shouldn't unless you like having unpredictable code). – chris Jul 08 '13 at 20:05
  • Ah, true... I keep forgetting how much C++ really does for me in the background haha – George Mitchell Jul 08 '13 at 20:06
  • @chris "you can't `malloc` a non-POD type" What about `CRectangle *d = new( malloc(2*CRectangle) ) CRectangle;`? (it lacks the basic exception guarantee, though) – dyp Jul 08 '13 at 20:14
  • @chris, you are correct, but it's because of the constructor call. – Joel Jul 08 '13 at 21:40