【发布时间】:2014-07-29 23:21:02
【问题描述】:
我到处寻找对此的解释,但我做不到。我从 VS2013 v120 平台工具集中看到了这种行为,但是当我将工具集设置为 v90(VS2008 工具集)时,一切都未初始化。我相信这是由于 C++11 的一些变化,但也可能是 v120 平台工具集的异常。
谁能解释一下 C++/C++11 级别的情况?也就是说,为什么b 被清零了?为什么j 也没有归零? (即为什么结构与类的行为不同)
另外,我知道我输出数据的方式是未定义的行为,请忽略它。以这种方式在此处发布比调试器窗口更容易。这是在 32 位上运行的,因此指针的大小与 unsigned int 相同。
考虑以下代码:
#include <iostream>
class Foo {
public:
int a,
*p;
};
class Bar {
public:
Bar(){}
int a,
*p;
};
struct Jar {
Jar(){}
int a,
*p;
};
int main() {
Foo f;
Bar b;
Jar j;
std::cout << std::hex; // please excuse this undefined-behavior producing test code, it's more simple to show this than a debugger window on SO (this is on 32-bit)
std::cout << "f: " << ((unsigned*)&f)[0] << ' ' << ((unsigned*)&f)[1] << std::endl;
std::cout << "b: " << ((unsigned*)&b)[0] << ' ' << ((unsigned*)&b)[1] << std::endl;
std::cout << "j: " << ((unsigned*)&j)[0] << ' ' << ((unsigned*)&j)[1] << std::endl;
return 0;
}
这是输出:
f: cccccccc cccccccc
b: 0 0
j: cccccccc cccccccc
编辑:
这是我看到的与Bar b; 相关的反汇编 __autoclassinit2 正在将内存归零。它不是构造函数的一部分,而是在构造函数调用之前归零。
Bar b;
00886598 push 8
0088659A lea ecx,[b]
0088659D call Bar::__autoclassinit2 (0881181h)
008865A2 lea ecx,[b]
008865A5 call Bar::Bar (0881109h)
【问题讨论】:
-
你问为什么一些未初始化的变量有一个值而其他的有不同的值?那是因为未初始化的变量具有不确定的值。正如您所指出的,使用这些值会产生未定义的行为。因此,您问题的唯一答案是“因为任何事情都可能发生”。
-
@Apriori:在所有三种情况下,所有成员都包含垃圾值。这里没有什么“归零”。如果您在输出中看到零,它们纯粹是偶然的,任何其他值也是如此。 IE。您的零是垃圾零,而不是确定性零。
-
@Mike Seymour:我说的是输出类型中的未定义行为,双关语值并将它们打印出来作为示例。但是在我的场景中(在我面前的机器上)我在调试器中查看它们,这就是我所看到的。当然,在调试器中查看变量不会触发未定义的行为。
-
@Apriori:很公平。您在调试器中看到的是未初始化内存的内容,其中可能包含任何内容。
-
然后,我的 Mac 上的 clang 3.4 提供了,
f: 1f30 20 b: 1f34 20 j: 1f38 20在 32 位发布模式下,f: 300 700 b: f00 1300 j: 1c00 2100在 64 位发布模式下。
标签: c++ visual-studio c++11