Search code examples
c++typessdlheap-memorynew-operator

C++: Strange behaviour of `new`


SDL provides me this struct:

typedef struct SDL_Rect {
    Sint16 x, y;
    Uint16 w, h;
} SDL_Rect;

I want to create a new SDL_Rect on the heap as class variable:

// Forward declaration
private:
    SDL_Rect *m_pcScreenRect;

And in the constructor I do this:

/* Screen Rectangle (for clearing) */
m_pcScreenRect = new SDL_Rect;
m_pcScreenRect->x = 0;
m_pcScreenRect->y = 0;
m_pcScreenRect->w = 800;
m_pcScreenRect->h = 600;
printf("Rect(x:%d, y:%d, w:%d, h:%d)\n", m_pcScreenRect->x, m_pcScreenRect->y, m_pcScreenRect->w, m_pcScreenRect->h);

Which prints Rect(x:0, y:0, w:800, h:600)
So this is correct.

Problem 1

But when I don't initialize x and y, it prints rubbish numbers like:

 Rect(x:-11280, y:63, w:800, h:600)
 Rect(x:25584, y:167, w:800, h:600)
 Rect(x:-11280, y:40, w:800, h:600)
 // This is just, run, terminate, run, terminate, ....

And I thought the default value for an int is 0?

Problem 2

In my gameloop, I have the same line to check the values of the SDL_Rect. In the loop I get results like this:

Clear (x:0, y:40, w:0, h:560)
Clear (x:0, y:99, w:0, h:501)
Clear (x:0, y:55, w:0, h:545)
Clear (x:0, y:55, w:0, h:545)
// Again: run, terminate, run, terminate....

When my constructor looks like this:

/* Screen Rectangle (for clearing) */
m_pcScreenRect = new SDL_Rect;
//m_pcScreenRect->x = 0;
//m_pcScreenRect->y = 0;
m_pcScreenRect->w = 800;
m_pcScreenRect->h = 600;

And I get normal results when I uncomment the two lines:

/* Screen Rectangle (for clearing) */
m_pcScreenRect = new SDL_Rect;
m_pcScreenRect->x = 0;
m_pcScreenRect->y = 0;
m_pcScreenRect->w = 800;
m_pcScreenRect->h = 600;

Does this problem something have to do with new or with the datatypes (Uint16, and a normal int). If it is with the datatypes, how to solve it?

Thanks would be very appreciated! (Haha!)

Thanks,
Any help would be very appreciated!


Extra Question:

I have to define all my variables in C++.
But from where do the random numbers come?

I'm using g++ and gcc in Linux.


Solution

  • In order to make use of the "default value for an int", you can use value initialization:

    m_pcScreenRect = new SDL_Rect(); // this will initialize to zeros
    

    Otherwise, the values are not defined.

    To give more details: adding a constructor to this structure would be the best approach, but since it's in a third-party library which you (I suppose) cannot modify, you can either wrap it in your own class that provides a default constructor, or use value-initialization. To quote C++03 8.5/5,

    To value-initialize an object of type T means:

    • if T is a class type with a user-declared constructor, then the default constructor for T is called

    • if T is a non-union class type without a user-declared constructor, then every non-static data member and base-class component of T is value-initialized;

    • if T is an array type, then each element is value-initialized;

    • otherwise, the object is zero-initialized

    In your case, SDL_Rect is a non-union class type without a user-declared constructor (second clause in this list), meaning value-initialization is performed for its non-static data memebers, and each of those data members falls under the "otherwise" clause, and is zero-initialized (which is defined as "if T is a scalar type, the object is set to the value of 0 (zero) converted to T;")