POD成员未初始化为0

时间:2013-06-24 13:14:09

标签: c++ class gcc g++ initialization

代码:

#include <iostream>

class cMapRender
{
public:
unsigned int m_rightMargin;
unsigned int m_bottomMargin;
unsigned int m_x;
unsigned int test;
unsigned int m_y;
unsigned int m_width;
unsigned int m_height;
};

int main(int argc, char **argv)
{
cMapRender mapRender;

std::cout << mapRender.m_x << std::endl; //gives random values (like 45321231)
std::cout << mapRender.m_height << std::endl;
std::cout << mapRender.m_width << std::endl;

return 0;
}

当我通过调试器运行它(或者只是cout一些值)时,这有可能是什么呢?有些成员是0而有些是随机值?我认为pod成员应该是0初始化。

我在linux上使用g ++ 4.7。当我在ideone.com上运行它时,在gcc 4.7上我也遇到了这个bug。但是,在ideone.com gcc 4.3中,每个成员都是0初始化的!

这里发生了什么,为什么成员并不总是0初始化? 我读到C标准说pod应该始终为0初始化。

3 个答案:

答案 0 :(得分:2)

取决于:

Standardese

  

<强> 8.5。初始值设定项[dcl.init] / 11

     

如果没有为对象指定初始化程序,则默认初始化该对象;如果没有执行初始化,则   具有自动或动态存储持续时间的对象具有不确定的值。 [注意:具有静态或。的对象   线程存储持续时间为零初始化,见3.6.2。 - 结束记录]

和(因可读性而反转):

  

<强> 8.5。初始值设定项[dcl.init] / 6

     

默认初始化 T类型的对象意味着:

     

- 如果T是(可能是cv限定的)类类型(第9节),则调用T的默认构造函数(并且   如果T没有可访问的默认构造函数,则初始化是错误的;)

     

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

     

- 否则,不会执行初始化。 [强调我的]

     

如果程序要求对const限定类型T的对象进行默认初始化,则T应为类类型   使用用户提供的默认构造函数。

它们是默认初始化。对于像intdouble这样的内置类型,它们的值取决于结构声明的位置(根据经验(但同样如此):假设它们总是垃圾,除非初始化

在全局范围或/和static存储中,它们都是零(包括当结构是全局范围的结构的成员时)。

在功能本地范围内,它们充满了垃圾。

示例:

#include <iostream>

struct Foo {
    int x;
    int y;
};

Foo foo;

int main () {
    Foo bar;

    std::cout << foo.x << ":" << foo.y << '\n';
    std::cout << bar.x << ":" << bar.y << '\n';
}

这是第一次运行给我

0:0
-1077978680:12574708

在第二次运行中,没有重新编译,这给了我:

0:0
-1075556168:12574708

POD结构可以使用例如全部零来初始化。 memset或只是......

Foo foo = {0}; // C and C++03
Foo foo{0}; // C++11

最后

您评论说您的代码依赖于这些成员的零初始化。这是你想要一个构造函数的地方:

class cMapRender
{
public:
    unsigned int m_rightMargin;
    unsigned int m_bottomMargin;
    unsigned int m_x;
    unsigned int test;
    unsigned int m_y;
    unsigned int m_width;
    unsigned int m_height;

    cMapRender() :
       m_rightMargin(0),
       m_bottomMargin(0),
       /* and so forth */
    {}
};

除了您班级的设计问题(更好地将一些变量组合成Rectangle - 类型),这将解决您的问题。


(注意:这个答案是我从另一个答案中复制和修改的(Initializing member variables of a struct in c++))

答案 1 :(得分:1)

语言规则表明您的数据成员未初始化。你可以像这样对它们进行初始化:

cMapRender mapRender{}; // C++11

cMapRender mapRender1 = {};           // C++03 and C++11
cMapRender mapRender2 = cMapRender(); // C++03 and C++11

这将初始化数据成员的值,这意味着0在这种情况下初始化。

答案 2 :(得分:1)

C ++语言是为“速度”而设计的。通过使语言标准定义“除非您专门为其编写代码,POD不是初始化”,编译器不必生成代码来将POD设置为某个特定值。这反过来意味着代码运行得更快,因为通常,您会立即将其设置为其他内容。

您可以拥有构造函数,或者如果需要,可以使用初始化对象将其设置为零。理想情况下,你有一个采用初始值的构造函数,所以这些值不会先设置为零,然后再设置为其他值 - 因为它看起来不像你的大多数值都有意义为零。