-2

编码:

#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;
}

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

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

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

4

3 回答 3

2

这取决于:

标准话

8.5。初始化程序 [dcl.init] / 11

如果没有为对象指定初始化器,则该对象是默认初始化的;如果不执行初始化,则具有自动或动态存储持续时间的对象具有不确定的值。[注意:具有静态或线程存储持续时间的对象是零初始化的,请参见 3.6.2。——尾注]

和(为了便于阅读,倒序排列):

8.5。初始化程序 [dcl.init] / 6

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

— 如果 T 是(可能是 cv 限定的)类类型(第 9 条),则调用 T 的默认构造函数(如果 T 没有可访问的默认构造函数,则初始化是非良构的);

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

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

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

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

在全局范围或/和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-struct 可以使用 egmemset或只是 ...

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++))

于 2013-06-24T13:18:00.910 回答
1

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

cMapRender mapRender{}; // C++11

或者

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

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

于 2013-06-24T13:16:33.440 回答
1

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

你可以有一个构造函数,或者你可以使用一个初始化对象将它设置为零,如果你需要的话。理想情况下,您应该有一个构造函数来获取初始值,因此这些值不会首先设置为零,然后设置为其他值 - 因为看起来您的大多数值无论如何都设置为零是没有意义的。

于 2013-06-24T13:21:48.413 回答