[英]C++ Default constructor
Given the following code: 给出以下代码:
class temp
{
public:
string str;
int num;
};
int main()
{
temp temp1;
temp temp2 = temp();
cout << temp1.str << endl; //Print ""
cout << temp2.str << endl; //Print ""
cout << temp1.num << endl; //Print a rand num
cout << temp2.num << endl; //Print 0
}
What is the different between these two?— 这两者有什么不同? -
temp temp1;
and 和
temp temp2 = temp();
temp temp1;
This calls temp
's default constructor on the instance called temp1
. 这会在名为
temp1
的实例上调用temp
的默认构造函数。
temp temp2 = temp();
This calls temp
's default constructor on a temporary object, then calls the compiler-generated copy-constructor on temp2
with the temporary object as the argument (this of course assumes that the compiler doesn't elide copies; it depends on your compiler's optimization settings). 这会在临时对象上调用
temp
的默认构造函数,然后在临时对象作为参数的情况下调用temp2
上编译器生成的复制构造函数(当然这假设编译器不会删除副本;它取决于编译器的优化设置)。
As for why you get different initialized values, section 8.5 of the standard is relevant: 至于为什么你得到不同的初始值,标准的第8.5节是相关的:
T
means:
T
类型的对象意味着:
T
is a scalar type (3.9), the object is set to the value of 0 (zero) converted to T
; T
是标量类型(3.9),则将对象设置为0(零)转换为T
; T
is a non-union class type, each nonstatic data member and each base-class subobject is zero-initialized; T
是非联合类类型,则每个非静态数据成员和每个基类子对象都是零初始化的; T
is a union type, the object's first named data member is zero-initialized; T
是联合类型,则对象的第一个命名数据成员为零初始化; T
is an array type, each element is zero-initialized; T
是数组类型,则每个元素都是零初始化的; T
is a reference type, no initialization is performed. T
是引用类型,则不执行初始化。 To default-initialize an object of type T
means: 默认初始化
T
类型的对象意味着:
T
is a non-POD class type (clause 9), the default constructor for T
is called (and the initialization is ill-formed if T
has no accessible default constructor); T
是非POD类类型(第9节),则调用T
的默认构造函数(如果T
没有可访问的默认构造函数,则初始化是错误的); T
is an array type, each element is default-initialized; T
是数组类型,则每个元素都是默认初始化的; To value-initialize an object of type T
means: 对值类型
T
的对象进行值初始化意味着:
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); T
是具有用户声明的构造函数(12.1)的类类型(第9节),则调用T
的默认构造函数(如果T
没有可访问的默认构造函数,则初始化是错误的); T
is a non-union class type without a user-declared constructor, then every non-static data member and base-class component of T is value-initialized; T
是没有用户声明的构造函数的非联合类类型,那么T的每个非静态数据成员和基类组件都是值初始化的; T
is an array type, then each element is value-initialized; T
是数组类型,那么每个元素都是值初始化的; So now that the rules have been laid out, let's see how they apply: 现在已经制定了规则,让我们看看它们是如何应用的:
temp temp1;
temp
is a non-POD type (because it has a std::string
member), and since no initializer is specified for temp1
, it will be default-initialized (8.5/9). temp
是非POD类型(因为它有一个std::string
成员),并且由于没有为temp1
指定初始化程序,因此它将被默认初始化(8.5 / 9)。 This calls the default constructor (8.5/5). 这会调用默认构造函数(8.5 / 5)。
temp
has an implicit default constructor (12/7) which default-initializes the std::string
member and the int
member isn't initialized at all (12.6.2/4). temp
有一个隐式默认构造函数(12/7),它默认初始化std::string
成员, int
成员根本没有初始化(12.6.2 / 4)。
temp temp2 = temp();
On the other hand, the temporary temp
object is value-initialized (8.5/7), which value-initializes all data members (8.5/5), which calls the default constructor in the std::string
member and zero-initializes the int
member (8.5/5). 另一方面,临时
temp
对象是值初始化的(8.5 / 7),它初始化所有数据成员(8.5 / 5),它调用std::string
成员中的默认构造函数并对int
零初始化成员(8.5 / 5)。
Of course, if you much rather not have to refer to the standard in 5+ different places, just ensure that you explicitly initialize everything (eg int i = 0;
or using initializer lists). 当然,如果您不必在5个以上的不同位置引用标准,只需确保明确初始化所有内容(例如
int i = 0;
或使用初始化列表)。
The behavior of your code depends critically on the compiler you are using. 代码的行为主要取决于您使用的编译器。 More precisely, it depends on which version of language specification your compiler implements.
更准确地说,它取决于编译器实现的语言规范版本。
For C++98 compilers, both declarations have identical effect on the final values of the objects being declared: the str
member should become empty, while the num
members should contain unpredictable value. 对于C ++ 98编译器,两个声明对声明的对象的最终值具有相同的效果:
str
成员应该变为空,而num
成员应该包含不可预测的值。 In both cases the actual initialization is default-initialization performed by a compiler-provided default constructor of class temp
. 在这两种情况下,实际初始化都是由编译器提供的类
temp
默认构造函数执行的默认初始化 。 That default constructor initializes str
, but leaves num
uninitialized. 默认构造函数初始化
str
,但是num
未初始化。
For C++03 compilers the behavior is different. 对于C ++ 03编译器,行为是不同的。 There's no difference for
temp1
object (its num
is still unpredictable). temp1
对象没有区别(它的num
仍然是不可预测的)。 But temp2
initialization is handled differently. 但是
temp2
初始化的处理方式不同。 In C++03 the ()
initializer triggers the new kind of initialization - so called value-initialization . 在C ++ 03中,
()
初始化程序触发了新的初始化 - 所谓的值初始化 。 Value-initialization ignores the compiler-provided default constructor of the top level object, and instead works directly on its subobjects (data members in this case). 值初始化忽略编译器提供的顶级对象的默认构造函数,而是直接在其子对象(本例中为数据成员)上工作。 So the
temp2
object is effectively initialized by value-initialization, which also sets the num
member to zero (in addition to initializing str
with an empty string). 因此,
temp2
对象通过值初始化有效地初始化,这也将num
成员设置为零(除了用空字符串初始化str
)。 For this reason, temp2.num
ends up being zero in C++03 compilers. 因此,
temp2.num
在C ++ 03编译器中最终为零。
If in your experiments you observed consistent zero in temp2.num
, it means that your compiler follows the C++03 specification in this respect. 如果在您的实验中您在
temp2.num
观察到一致的零,则意味着您的编译器在这方面遵循C ++ 03规范。
temp temp1;
Will create a default initialized temp
object. 将创建默认的初始化
temp
对象。 Since you provided no default constructor for temp
, every member of temp
will be default initialized too. 由于您没有为
temp
提供默认构造函数,因此每个temp
成员也将默认初始化。 Since std::string
provides a default ctor, it gets initialized correctly and has a well-defined value. 由于
std::string
提供了一个默认的ctor,它会被正确初始化并具有明确定义的值。 The integer, however, gets default initialized, which is implementation defined and normally a random value. 但是,整数默认初始化,这是实现定义的,通常是随机值。
temp temp2 = temp();
This will first create a value initialized temp
object. 这将首先创建一个值初始化的
temp
对象。 This is important, because the object itself is value initialized, so are its members. 这很重要,因为对象本身是值初始化的,其成员也是如此。 It doesn't matter for the string, as default and value initialization are the same, but it matters for the integer.
对于字符串没有关系,因为默认值和值初始化是相同的,但它对整数很重要。 A value initialized integer has the value
0
. 值初始化整数的值为
0
。
After that, you just copy over those members into temp2
. 之后,您只需将这些成员复制到
temp2
。
Also, this relevant question might be of interest to you. 此外,您可能会对此相关问题感兴趣。
Edit : See my comment on @In silico's answer for explanation on why this isn't the case for MSVC. 编辑 :请参阅我对@In silico答案的评论,以解释为什么MSVC不是这种情况。 :/
:/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.