2010-06-22 78 views
1

SDL奇怪的行为,为我提供了这样的结构:C++:中`new`

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

在我gameloop,我有同样的线路检查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

+0

随机数字来自新变量分配给的内存位置。他们之前获得了这个地点的任何价值。简单的例子:如果你分配一个100字节的数组,给它们分配一些值,释放它并且分配一个25个整数的数组(4个字节的整数是准确的),它们可能(取决于很多因素)每个得到4个先前分配的100个字节的字节,并取出这些字节在释放时的值。如果前4个字节是0x00010203,则生成的整数将为66051,否则直接进行初始化。 – dbemerlin 2010-06-22 12:13:15

回答

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是一个没有用户声明的构造不连级型(在此列表中第二条),这意味着价值 - 为其非静态数据记忆体执行初始化,并且每个数据成员落在“其他”子句下,并且被初始化为零(它被定义为“如果T是标量类型,则该对象被设置为值0(零)转换为T;“)

+0

@Cubbi:那么差异是'()'?这个差异是否有名字?我想了解它。 – 2010-06-22 11:18:06

+2

@Martijn名称是“值初始化”(或“值初始化”)。它是C++ 98和C++ 03之间的主要区别。 – Cubbi 2010-06-22 11:23:29

+1

@Martijn:内置插件有所不同。尝试谷歌,如果我记得正确的条款,“值初始化”与“默认初始化”。 – sbi 2010-06-22 11:24:56

2

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

1

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

+1

是的,的确如此,但您并不需要为所有类型明确这样做。如果一个类有一个'std :: string'成员,它也将被隐含地初始化。 – sbi 2010-06-22 11:23:27

+0

那是因为std :: string有一个构造函数,int,char,float等没有。 – dbemerlin 2010-06-22 12:15:23

3

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

+0

@dbemerlin :(和其他人)谢谢你的信息。对于所有人+1! – 2010-06-22 11:26:05

+0

第一句话并不普遍。用户定义的类型将为你隐式初始化:struct X {std :: string m; }; X x;'。 – sbi 2010-06-22 11:26:14

1

我想如果你希望你的类数据成员被初始化为一个给定的值(包括0),你应该明确地在构造函数中赋值。

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

+0

但是,struct X {std :: string m; X(){}};'很好。它只是内置的,隐式初始化没有完成。 – sbi 2010-06-22 11:27:56

0

把一个构造函数放在你的struct中:

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

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

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