我正在阅读cplusplus.com.中的课程教程
我被下面这段话弄糊涂了。
默认构造类的所有成员可能很方便,也可能总是不方便:在某些情况下,这是一种浪费(当成员在构造函数中重新初始化时(,但在其他一些情况下,默认构造甚至是不可能的(当类没有默认构造函数时(。在这些情况下,应在成员初始化列表中对成员进行初始化。
所以,我的问题是;当该成员然后在构造函数"中被重新初始化时;意思是为什么是浪费?
一开始,我认为;重新初始化,就像下面的代码一样。
class Son
{
int age;
public:
// default constructor
Son()
{
age = 1;
}
Son(int age) : age(age) {}
};
class Father
{
Son son; // First, I think that it will call default constructor of class Son when the object of Father was created
int age;
public:
// Then object of Father will call this constructor, then initialize son again.
Father(int sonAge, int fatherAge) : son(sonAge), age(fatherAge)
{
}
};
然后,我发现Son son
根本不是定义子,它只是等待Father的构造函数初始化son
。所以这不是浪费,我的想法是错误的!!!也许我缺乏对物体创造顺序的了解?cplusplus.com提供的教程对我来说似乎不完整…
你能给我举几个代码示例吗?
在输入构造函数的主体之前,所有对象都已初始化,所以让我们逐步完成:
int age;
Son() // age initialized here (does nothing)
{
age = 1;// age assigned new value here
}
但是,如果年龄比int
更复杂呢?如果它是一个建筑非常昂贵的班级呢?
Expensive age;
Son() // age initialized here takes a lot of time and resources
{
age = 1;// age assigned new value here. This requires construction of a
// temporary Expensive (which takes a lot of time and resources)
// and then assigns the temporary to age (which may also be time and
// resource-consuming), wasting the effort spent on the default
// construction. The temporary is then destroyed, and that wastes
// even more
}
如果使用成员初始化程序列表
Expensive age;
Son(): age(1) // age initialized here takes a lot of time and resources
{
// does nothing
}
注:以上是最坏的情况。Expensive
可以有一个Expensive &operator=(int)
来减少一些工作,但您仍然需要处理默认构造和赋值逻辑,而不是单个构造函数调用。另外,必须有人编写=
重载,并且不存在的代码没有错误。
所以,我的问题是;当该成员然后在构造函数"中被重新初始化时;意思是
没有";重新初始化";。每个对象都只初始化一次(尽管初始化可能是真空,这意味着它实际上什么都不做;在某些情况下,在实际初始化之前没有初始化,这可能被视为两次初始化(。作者的意思是初始化后的赋值。
在您的示例中,构造函数会发生这种情况
Son()
{
age = 1;
}
此构造函数没有成员初始化器,这意味着成员age
(其声明中也没有默认初始化器(将被默认初始化。只有在初始化之后,才执行构造函数的主体并完成赋值age = 1;
。
现在,在这种情况下,基本上没有浪费,因为int
的默认初始化不会做任何事情(它使值不确定(。然而,假设age
是std::string
,而分配是age = "1";
。然后,您将首先调用std::string
的默认构造函数以初始化age
,然后将"1"
分配给age
。第一个步骤是多余的,使用初始化器列表Son() : age("1") { }
可以避免额外的步骤。(是否真的会有任何性能差异取决于许多因素,编译器可能足够好,可以将两者优化到相同的机器代码。(
一个问题是";初始化";它在口语中的用法与上述技术含义不同。通俗地说,它可以指一个变量第一次设置其值。在这种情况下,分配age = 1;
将被视为初始化age
,尽管这是分配,而不是初始化。当谈到一个变量未初始化时,这个意思最常被使用,从技术上讲,更正确的应该是的值不确定。