0

The main issue is with creating a dynamic class. What I did:

ptr = new animal[2];

I'm trying to create a dynamic array of size 2, pointed by the pointer ptr. The issue arises when I try these operations:

ptr[0].setspeed(9);
ptr++->setspeed(13);

I am using DDD (gdb graphical) debugger and when I display ptr, I only see it pointing to one object. When I try to set the speed, the first one seems to work, but the second one won't (the speed is on the default of 0). Printing only gets garbage.

I am not so sure what's going on, please help.

Also when I do:

ptr->print();

Is it supposed to print for both ptr[0] and ptr[1], or just ptr[0]?

Also, can someone quickly draw a picture of how the ptr and new dynamic class look like? The way I see it, it is a ptr pointing to an array, array size of two, each one has an animal object.

#include <iostream>
using namespace std;

class animal
{
    private:
        int speed;
        double position_x;
        double position_y;

   public:
        animal() : speed(0), position_x(0), position_y(0)
        {
        }

        animal (int v, double x, double y)
        {
            this->speed = v;
            this->position_x = x;    
            this->position_y = y;
        }

        animal(const animal & g)
        {
            this->speed = g.speed;
            this->position_x = g.position_x;  
            this->position_y = g.position_y;
        }

        ~animal();

        void print();

        int getspeed() { return this->speed; }

        int getx() { return this->position_x; }

        int gety() { return this->position_y; }

        void setspeed(int s) { this->speed = s; }
   };

    void animal::print()
    {
        cout << "speed: " << this->getspeed() << endl;
        cout << "position_x: " << this->getx() << endl;
        cout << "position_y: " << this->gety() << endl;
    }

    int main()
    {
        animal *ptr;
        ptr = new animal;
        ptr = new animal [2];

       ptr[0].setspeed(9);
       ptr++->setspeed(13);

       ptr->print();
       cout << ptr[0].getspeed() << endl;
       cout << ptr[1].getspeed();

       return 0;
    }
Gustavo Mori
  • 8,319
  • 3
  • 38
  • 52
Rave
  • 835
  • 4
  • 15
  • 28
  • 5
    Best help: Screw dynamic arrays, get a `std::vector`. – Xeo Feb 02 '12 at 02:34
  • thanks, but i want to understand this ( i mean i really want to understand this), that's why i am doing it. i will look into the "vector" thanks – Rave Feb 02 '12 at 02:36
  • 2
    "ptr = new animal; ptr = new animal [2];" Maybe this is just a typo but it is a memory leak. – Duck Feb 02 '12 at 02:40
  • actually i kinda did the on purpose to see it on the debugger how the picture changes, i take that off, to stop memory leak. – Rave Feb 02 '12 at 02:41
  • 1
    Want pictures? http://stackoverflow.com/questions/8839943/why-is-it-a-memory-leak-what-could-i-catch-if-i-shall-use-such-things-in-c/8840302#8840302 – R. Martinho Fernandes Feb 02 '12 at 02:43
  • @R.MartinhoFernandes wow nice answer in that link, +1. But it does need more freehand circles. – Seth Carnegie Feb 02 '12 at 02:55
  • In the debugger watch window, can you put 'ptr, 2' to see both objects – Chanakya Sep 28 '14 at 19:49

4 Answers4

6

Instead of

ptr[0].setspeed(9);
ptr++->setspeed(13);

You could use the more intuitive and even more correct

ptr[0].setspeed(9);
ptr[1].setspeed(13);

When you do a ++, you are changing the value of ptr, so it will point to the next element. You should keep a pointer to the start of the array so you can delete[] it later.

Also, ptr++ increments the pointer but returns the old value. Maybe you wanted (++ptr)->setspeed(13), which will increment and use the new value in the rest of the expression.

As for your other question, ptr->print() is the same as ptr[0].print(), and (ptr+1)->print() is the same as ptr[1].print(). There is no built-in syntax to call print() on all elements.

Seth Carnegie
  • 73,875
  • 22
  • 181
  • 249
marcus
  • 5,041
  • 3
  • 30
  • 36
6

Ok, someone pointed out the memory leak issue to you already.

So, you have allocated an array of two animals (ptr = new animal [2];), and stored a pointer to the first one in ptr.

+----------+----------+
| speed: 0 | speed: 0 |
+----------+----------+
     ^
     |
     |
    ptr

(I'm ignoring the position_x and position_y, for the sake of space)

Then you set the speed of the first one to 9 (ptr[0].setspeed(9);):

+----------+----------+
| speed: 9 | speed: 0 |
+----------+----------+
     ^
     |
     |
    ptr

Then you do something very weird.

ptr++->setspeed(13);

Why you do this, I don't know. Don't do this. I'm not joking. I can figure out what this code means, but I would never write something like this. It only serves to sow confusion.

But let's pretend it is a sane thing to do for a while... ptr++ increments the pointer, and returns the old value.

+----------+----------+
| speed: 9 | speed: 0 |
+----------+----------+
      ^          ^
      |          |
      |          |
    result      ptr
   of ptr++

... and then it sets the speed of the animal pointed by that result to 13.

+-----------+----------+
| speed: 13 | speed: 0 |
+-----------+----------+
      ^          ^
      |          |
      |          |
    result      ptr
   of ptr++

Finally, ptr->print() prints the the animal pointed by ptr, which is the second one.

Community
  • 1
  • 1
R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
  • so after i do ptr++, i am at ptr[1], if i call delete [] ptr, then only ptr[1] gets deleted and ptr[0] is now a memory lead? – Rave Feb 02 '12 at 03:45
  • @Rave: actually, that's way worse. You can only `delete[]` pointers that were provided by `new []`, so `delete[] ptr` now that it points to the second one is undefined behaviour. You need to decrement the pointer back to the beginning to `delete[]`. – R. Martinho Fernandes Feb 02 '12 at 03:50
5

My c++ is rusty, but here's what I think:

    ptr++->setspeed(13);

This is a post-increment. ptr is first evaluated and then incremented. Meaning that setspeed is called on the original value of the pointer.

Personally, I think that this style of code is unacceptable and I'd fire anyone who writes this. It's hard to read and it should be easy to read and understand.

Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367
  • And don't forget to decrement the pointer to get back to the beginning of the array. – Beta Feb 02 '12 at 02:40
0

If the ++ operator is after the variable(ptr++), it will first does the evaluation and then the increment. It means this statement

ptr++->setspeed(13);

works as

ptr->setspeed(13)  // ptr point to animal[0]
ptr++              // ptr point to anima[1] after this statement

And ++ptr->setspeed(13) will work in opposite way.

Now you can see where the problem is. You actually call setspeed(13) on animal[0], and the call print() on animal[1].

Fan Zhang
  • 19
  • 6
  • Beware of operator precedence. The expression ++ptr->setspeed(13) means ++(ptr->setspeed(13)) i.e. increments the return value (if it existed) of the function call (not tested, but I have checked this table [ http://msdn.microsoft.com/en-us/library/126fe14k%28v=vs.71%29.aspx ] before posting). – marcus Feb 02 '12 at 03:15
  • Yes. It should be (++ptr)->setspeed(13) – Fan Zhang Feb 02 '12 at 03:59