初始化新对象时的C ++默认构造函数和POD问题

时间:2019-05-21 13:41:04

标签: c++ constructor initialization default-constructor

我理解默认构造函数和用户提供的空构造函数之间的区别(至少我相信我理解)以及POD的含义。但是,在对象初始化期间有些行为我不太了解:

#include <iostream>
using namespace std;
//POD
struct A {
    int a, b, c;
};

//Not POD
struct B {
    B() {};
    int a, b, c;
};

int main(){

A a = {1,2,3} \\ Case 1. Works, this is how we initialize a POD type
B b1 = {1,2,3} \\ Case 2. Doesn't work, since B is not POD
B b2;          \\ Case 3. Works, call the user provided empty constructor but a, b and c are not initialized
A c{};        \\ Case 4. Works, initialize everything to 0
A d;          \\ Case 5. Doesn't work. This is the case I don't understand
cout << a.a << a.b << a.c << endl;
cout << b1.a << b1.b << b1.c << endl;
cout << b2.a << b2.b << b2.c << endl;
cout << c.a << c.b << c.c << endl;
cout << d.a << d.b << d.c << endl;
}

如上所述,情况5是我不了解的行为。我期望它会调用默认构造函数并将每个成员初始化为0。但是,出现编译错误:

使用了错误C4700未初始化的局部变量'd'

任何人都可以帮助我了解为什么它会报告上述错误吗?我在Windows上运行并使用Visual Studio编译器。

2 个答案:

答案 0 :(得分:2)

回答问题的另一个方面,即“ PODness ”。

POD是一个遗留定义,由于它无法涵盖各种情况,因此已不再使用。在C ++ 20中为deprecated。相反,使用各种术语来讨论与C结构的类兼容性(因为最后,这就是它的全部内容)。

尤其是最重要的属性(至少在我看来)是:

  • Standard layout:这很重要,因为用外行术语来说,当类是标准布局时,该对象可以被视为字节序列,然后发送到其他程序(可能用不同的语言编写)并进行重构在接收端从该序列开始(考虑填充)。当实体序列化的数据通过网络发送或保存到文件中时,这起了很大的作用
  • Trivially copyable:这很重要,因为当类是可微复制的时,可以仅通过内存复制一个对象的字节来从另一个对象创建一个对象。这在优化中起着很大的作用
  • Trivial type,是对Trivially Copyable要求的扩展:这很重要,因为当class为琐碎类型时,任何随机字节序列都可以被视为该类型的有效对象(在考虑了内存别名之后) 。

答案 1 :(得分:0)

Error C4700 uninitialized local variable 'd' used
     

任何人都可以帮助我了解为什么它会报告上述错误吗?

该错误表示您(可能是?)读取了不确定的值。读取不确定值的行为是不确定的(忽略某些显然不适用于您的情况的异常)。

似乎编译器已确定您在初始化之前使用d(的成员)的值,并且它试图通过诊断问题来提供帮助。

从技术上讲,读取不确定的值不会使程序格式错误,因此不允许其阻止编译。您可能已将编译器配置为通过在发生警告的情况下拒绝编译而故意违反标准。如果您还没有这样做,那么这可能是编译器中的一致性错误。

解决方案:不要读取不确定的值。您可以将初始化值设置为零,也可以列出其他值的初始化值。参见示例1和4。


有关术语的较小更正:

  

情况3.工作,调用用户提供的空构造函数,但将a,b和c初始化为随机垃圾值

更准确地说:成员没有被初始化,可能还剩下不确定值的 1

1 在您的示例中,您声明了具有静态存储的变量。这些在动态初始化之前首先被零初始化。这样,在您的示例中,成员没有不确定的值,而是零。

  

情况4。工作,通过调用默认构造函数将所有内容初始化为0

int没有“默认构造函数”。它们是价值初始化的。 int的值初始化为零初始化。