C ++: странное поведение `new` - PullRequest
1 голос
/ 22 июня 2010

SDL предоставляет мне эту структуру:

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

Я хочу создать новую SDL_Rect в куче как переменную класса:

// Forward declaration
private:
    SDL_Rect *m_pcScreenRect;

И в конструкторе я делаю это:

/* 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);

Какие отпечатки Rect(x:0, y:0, w:800, h:600)
Так что это правильно.

Задача 1

Но когда я не инициализирую x и y, он печатает мусорные числа вроде:

 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, ....

И я думал, что значением по умолчанию для int является 0?

Задача 2

В моем игровом цикле у меня есть та же строка, чтобы проверить значения SDL_Rect. В цикле я получаю следующие результаты:

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....

Когда мой конструктор выглядит так:

/* 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;

И я получаю нормальные результаты, когда раскомментирую две строки:

/* 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;

Имеет ли эта проблема какое-то отношение к new или к типам данных (Uint16 и обычный int). Если это с типами данных, как решить это?

Спасибо, буду очень признателен! (Ха-ха!)

Спасибо
Любая помощь будет принята с благодарностью!


Дополнительный вопрос:

Я должен определить все свои переменные в C ++.
Но откуда взялись случайные числа?

Я использую g++ и gcc в Linux.

Ответы [ 7 ]

5 голосов
/ 22 июня 2010

Чтобы использовать «значение по умолчанию для целого», вы можете использовать инициализацию значения:

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

В противном случае значения не определены.

Чтобы дать большедетали: добавление конструктора в эту структуру было бы лучшим подходом, но, поскольку он находится в сторонней библиотеке, которую вы (я полагаю) не можете изменить, вы можете либо обернуть его в свой собственный класс, предоставляющий конструктор по умолчанию, либо использовать значение-initialization.Процитировать C ++ 03 8.5 / 5,

Инициализация значения объекта типа T означает:

  • , если T является типом класса собъявленный пользователем конструктор, тогда конструктор по умолчанию для T называется

  • , если T является типом класса без объединения без конструктора, объявленного пользователем, тогда каждый нестатический член данных и база-класс компонента T инициализируется значением;

  • , если T является типом массива, то каждый элемент инициализируется значением;

  • в противном случаеобъект инициализируется нулями

В вашем случае SDL_Rect - это тип класса без объединения без конструктора, объявленного пользователем (второе предложение в этом списке), что означает значение-инициализация выполняется для его нестатических элементов данных, и каждый из этих элементов данных подпадает под условие «иначе» и инициализируется нулями (что определяется как «если T является скалярным типом, объект устанавливается назначение 0 (ноль) преобразуется в T; ")

3 голосов
/ 22 июня 2010

Если вы не инициализируете переменную, то ее значение не определено. Для целых чисел, выделенных в куче, значения по умолчанию нет.

2 голосов
/ 22 июня 2010

AFAIK, по умолчанию нет значений для int и других не классовых типов в C ++.

1 голос
/ 22 июня 2010

Я думаю, что если вы хотите, чтобы ваши члены класса были инициализированы с заданным значением (включая 0), вам просто нужно явно назначить это в конструкторе.

IIRC, в отладочных сборках MSVC заполняет выделенное, но неинициализированное пространство кучи шаблоном 0xCDCDCDCD.

1 голос
/ 22 июня 2010

В C ++ вы всегда должны инициализировать все свои переменные.

0 голосов
/ 22 июня 2010

Вы должны инициализировать значения, если хотите, чтобы они имели значение по умолчанию.Когда вы создаете структуру, используя new SDL_Rect, вы просто распределяете память, а содержащиеся в ней данные - это просто данные, которые находятся в этом месте кучи при выделении, так что это примерно случайно.Вы можете использовать конструктор для инициализации переменных, так как компилятор автоматически создает его, если вы на него ссылаетесь, то есть new SDL_Rect()

0 голосов
/ 22 июня 2010

Поместите конструктор в вашу структуру:

typedef struct SDL_Rect {
    SDL_Rect() { x = 0; y = 0; w = 0; h = 0; }

    Sint16 x, y;
    Uint16 w, h;
} SDL_
...