C ++:`new`的奇怪行为

时间:2010-06-22 11:07:34

标签: c++ types heap new-operator sdl

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

但是当我没有初始化xy时,会打印出如下垃圾编号:

 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 ++定义所有变量 但随机数从何而来?

我在Linux中使用g++gcc

7 个答案:

答案 0 :(得分:5)

为了使用“int的默认值”,您可以使用值初始化:

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

否则,未定义值。

要提供更多详细信息:向此结构添加构造函数是最好的方法,但由于它位于您(我想)无法修改的第三方库中,您可以将其包装在您自己的类中,该类提供了默认构造函数,或使用值初始化。引用C ++ 03 8.5 / 5,

  

对T类型的对象进行值初始化意味着:

     
      
  • 如果T是具有用户声明的构造函数的类类型,则调用T的默认构造函数

  •   
  • 如果T是没有用户声明的构造函数的非联合类类型,那么T的每个非静态数据成员和基类组件都是值初始化的;

  •   
  • 如果T是数组类型,则每个元素都是值初始化的;

  •   
  • 否则,该对象为零初始化

  •   

在您的情况下,SDL_Rect是一个非联合类类型,没有用户声明的构造函数(此列表中的第二个子句),这意味着对其非静态数据成员执行值初始化,并且每个数据成员都会丢失在“otherwise”子句下,并且是零初始化(定义为“如果T是标量类型,则将对象设置为0(零)转换为T的值”;)

答案 1 :(得分:3)

如果您没有初始化变量,那么它的值是未定义的。堆分配的整数没有默认值。

答案 2 :(得分:2)

AFAIK,int和C ++中的其他非类类型没有默认值。

答案 3 :(得分:1)

在C ++中,您必须始终初始化所有变量。

答案 4 :(得分:1)

我认为如果您希望将类数据成员初始化为给定值(包括0),则应该在构造函数中明确指定它。

IIRC,在调试版本中,MSVC使用0xCDCDCDCD模式填充已分配但未初始化的堆空间。

答案 5 :(得分:0)

在结构中放置一个构造函数:

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

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

答案 6 :(得分:0)

如果您希望它们具有默认值,则必须初始化值。使用new SDL_Rect创建结构时,只需分配内存,其中包含的数据就是分配时堆的这个位置所在的数据,因此大致是随机的。您可以使用构造函数初始化变量,因为如果您引用变量,编译器会自动创建变量,即new SDL_Rect()