C++ 为什么我需要一个构造函数?

C++ 为什么我需要一个构造函数?,c++,oop,constructor,C++,Oop,Constructor,这没关系!我可以编译它!为什么在使用隐式定义的构造函数时无法编译它?因为I未初始化 class A { public: A() {} int i; }; “隐式构造函数”是指自动为您生成的构造函数,并生成错误,因为它意识到它无法初始化i的值。它可以是无参数构造函数、复制构造函数或(从C++11开始)移动构造函数 为什么隐式定义的构造函数不起作用 它工作得很好,但它不会隐式地决定默认值是什么(因此,它只为其成员调用默认构造函数,而不为POD类型调用默认构造函数) 如果希望构造函数使用某些

这没关系!我可以编译它!为什么在使用隐式定义的构造函数时无法编译它?

因为
I
未初始化

class A {
public:
  A() {}
  int i;
};
“隐式构造函数”是指自动为您生成的构造函数,并生成错误,因为它意识到它无法初始化
i
的值。它可以是无参数构造函数、复制构造函数或(从C++11开始)移动构造函数

为什么隐式定义的构造函数不起作用

它工作得很好,但它不会隐式地决定默认值是什么(因此,它只为其成员调用默认构造函数,而不为POD类型调用默认构造函数)

如果希望构造函数使用某些值初始化成员,则必须显式编写该值(即显式添加默认构造函数)

让一个默认(隐式)构造函数用一个选择的值初始化POD成员(比如零)会在您不需要的时候增加额外的计算周期(并降低程序的速度)。C++的设计是为了表现你(程序员)知道你在做什么(即如果你没有明确地初始化你的成员,编译器假设你不在乎你得到什么默认值)。 为什么隐式定义的构造函数不起作用

它确实有效,但语言规则之一是,除非初始化所有成员,否则不能使用它初始化
const
对象;而且它不会用诸如
int
之类的琐碎类型初始化成员。这通常是有道理的,因为作为
const
以后无法给它们一个值

(这有点简化;请参阅《语言标准》中的章节注释。)

如果您定义了自己的构造函数,那么您的意思是您知道自己在做什么,并且不希望初始化该成员。编译器将允许您将其用于
const
对象

如果要将其设置为零,则可以对对象进行值初始化:

class A 
{ 
    public:
    A()
    {
        i =0;
    }
    int i;
};
如果要将其设置为另一个值,或在用户不必指定值初始化的情况下将其设置为零,则需要一个初始化成员的构造函数:

const A aa {};    // C++11 or later
const A aa = A(); // historic C++

您没有说明正在使用的编译器。我在VS2012上尝试过这个,得到了一个警告

这是一个问题的原因是
aa
const
。因为您没有定义构造函数,所以使用默认构造函数,因此
i
可以是任何东西。它也不能更改(因为
aa
是常量)

如果定义构造函数,则假定您对
i
的初始化感到满意。不过,在这种情况下,您实际上并没有改变行为

由此

因为类的这个实例是在堆栈上生成的,所以m_数据的初始值可以是任何值。此外,由于它是一个常量实例,因此m_数据的值永远无法更改

为什么隐式定义的构造函数不起作用

因为C++标准是这样说的:

[dcl.init]第7段: 如果程序调用常量限定类型的对象的默认初始化,
T
T
应为具有用户提供的默认构造函数的类类型

这可以确保您不会创建包含未初始化数据的
const
对象,这些数据以后无法初始化

要初始化常量限定对象,您需要有用户提供的默认构造函数或使用初始化器:

A() : i(whatever) {}
这里,对象
aa
用表达式
A()
初始化,该表达式是一个值初始化对象。您可以在没有默认构造函数的情况下对类类型进行值初始化,因为如果该类型没有默认构造函数,则值初始化会将值设置为零


但是,标准中的规则太严格了,因为它禁止使用隐式定义的构造函数,即使没有数据成员或所有数据成员都有合理的默认构造函数,因此有一个针对标准的缺陷报告建议更改它,请参见。

您没有在此处声明任何构造函数。您的意思是,“这没问题”?你的构造函数也不会初始化
i
。我的意思是我可以编译它;所以说得很清楚,你问的是,如果你没有定义构造函数,为什么会出现编译器错误,而如果你定义的构造函数没有初始化值,为什么会出现编译器错误?你说的“不工作”是什么意思?“你如何确定它是否有效?你期待什么?实际发生了什么?“除非初始化所有成员,否则不能使用它初始化常量对象”这不是规则,规则是:“如果程序调用常量限定类型
t
的对象的默认初始化,
t
应为具有用户提供的默认构造函数的类类型。”也许你想的是
constexpr
构造函数。@JonathanWakely:也许我在简化规则,因为我懒得为每个答案引用章节。但是谢谢你的更正。事实上,有一个OpenDR建议将它改为你所说的,所以你很快就会对的:)我的编译器g++(Ubuntu/Linaro 4.7.3-1ubuntu1)4.7.3
A() : i(whatever) {}
const A aa = A();