值初始化和非 POD 类型

18
一个小时前,我在这里发布了一个答案(链接),我认为我的回答是正确的。然而,我的回答被Martin B给踩了。他说:

你只是幸运地得到了零值,因为分配给i的内存恰好被初始化为零。这不能由标准保证。

然而,在阅读Michael Burr的回答(链接)并尝试以下示例代码后:

1)

#include <cassert>

struct B { ~B(); int m; };

int main()
{
   B * b = new B();
   assert(b->m == 0);
}

我在MSVC++ 2010上遇到了一个调试错误。

当我在MSVC++2010上尝试以下代码[我的回答在这里]时,我遇到了类似的错误。

2)

#include <cassert>
struct Struct {
    std::string String;
    int Int;
    bool k;
    // add add add
};

struct InStruct : Struct
{
   InStruct() : Struct() {}
};

int main()
{
   InStruct i;
   assert(i.k == 0);
}
(1)(2)在gcc/Clang上都没有出现任何错误,这让我想到MSVC++2010是否不支持C++03。我不确定。
根据Michael Burr在[C++03]中的帖子:
new B() - value-initializes B which zero-initializes all fields since its default ctor is compiler generated as opposed to user-defined.
标准规定:
To value-initialize an object of type T means: — if T is a class type (clause 9) with a user-declared constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor); ..... otherwise, the object is zero-initialized
从第一点可以看出,如果没有用户声明的默认构造函数,则会调用由编译器合成的默认构造函数,该函数将零初始化所有字段(根据最后一点)。
那么我错在哪里呢?我的值初始化解释正确吗?

6
这是您的编译器:http://connect.microsoft.com/VisualStudio/feedback/details/564268/c-value-initialization http://connect.microsoft.com/VisualStudio/feedback/details/484295/vc-does-not-value-initialize-members-of-derived-classes-without-user-declared-constructor https://connect.microsoft.com/VisualStudio/feedback/details/100744/value-initialization-in-new-expression - CB Bailey
4
@Charles :非常感谢您提供这些链接。如果您把您的评论作为答案发布,我会接受它。:) - Prasoon Saurav
@Naveen:是的!他的评论是不正确的 :) - Prasoon Saurav
2
@Naveen:是的。很可能他在VS中遇到了这个问题,然后错误地得出了结论。如此基础的东西没有被正确实现,真是遗憾。 - GManNickG
1
大家好:感谢你们的教育! - Martin B
显示剩余6条评论
2个回答

33

Visual Studio在所有当前版本(2005、2008、2010)中都存在已知的错误,即对于没有用户声明构造函数的非POD类型,它不能正确地实现值初始化。

根据语言规则,这些断言中不应该出现任何问题,但确实表现出编译器问题。以下是一些漏洞报告,请注意它们都已关闭或解决为“无法修复”。

http://connect.microsoft.com/VisualStudio/feedback/details/564268/c-value-initialization

http://connect.microsoft.com/VisualStudio/feedback/details/484295/vc-does-not-value-initialize-members-of-derived-classes-without-user-declared-constructor

http://connect.microsoft.com/VisualStudio/feedback/details/100744/value-initialization-in-new-expression


1
+1 和...哇,我仔细阅读了那些反馈条目,感到震惊。在 OP 的第一个代码片段中,只有当存在用户提供的析构函数时才会出现问题。如果没有用户提供的析构函数,则变量会被正确初始化。因此,这为许多代码缺陷留下了空间,所有理智的 Visual C++ 开发人员都应该更好地意识到这个问题。 - sharptooth
2
@Naveenn:现有的代码库。我认为,每当他们没有正确实现某些东西时(比如他们对typename关键字的放任),他们至少应该发出警告。 - Alexandre C.
7
“所有理智的Visual C++开发人员”,我不知道你们如何能在使用Visual C++时保持理智。我发现保持理智的唯一方法就是停止使用它 :x。” - Matthieu M.
1
@Matthieu M. 你转换到了哪个? - mlvljr
1
@mlvljr:使用clang而非mingw支持的CodeBlocks。下一步是在虚拟机中运行完整的Linux进行编译。当然,我只是为了好玩尝试了一下Visual Studio,并不需要交付Windows软件 ;) - Matthieu M.
显示剩余4条评论

9

如果您在2015年或之后看到这个问题:

所有上述问题都已在VS 2015中得到解决。值初始化现在按照标准定义工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接