大家好!今天我来介绍一下C++中的构造函数初始化列表。
构造函数初始化列表是C++11的新特性,是在定义类的构造函数时使用的一种特殊语法。它允许我们在创建对象时直接初始化成员变量,而不是在构造函数体内逐个赋值。
1.定义
初始化列表位于构造函数的函数体之前,使用冒号(:)表示。初始化列表由逗号分隔的初始化器列表组成,每个初始化器包含一个成员变量和其对应的初始值。例如:
class A {
public:
A()
: m_a(1)
, m_b(2)
, m_c(3)
{
cout << "constructA\n";
}
}
上述代码对类A的三个成员变量m_a、m_b和m_c分别进行了赋值。
2.应用场景
首先,构造函数初始化列表的主要作用是初始化类的成员变量。使用初始化列表可以直接为成员变量赋初值,而不需要在构造函数体内逐个赋值。这样可以提高代码效率和可读性,对于具有大量成员变量或常量成员的类更加好用。
其次,常量成员只能在初始化列表中进行初始化,因为它们在对象创建后不能再修改。引用成员也需要在初始化列表中进行初始化,因为引用必须在创建对象时引用一个有效的对象。其实我们可以理解为,构造函数初始化列表的调用时机是在成员变量被默认初始化之前。根据这个特点,我们可以得出初始化列表的一个重要作用:减少构造函数的调用次数,从而提升性能,我们看下面这个例子:
class A {
public:
A()
: m_a(1)
, m_b(2)
, m_c(3)
{
cout << "constructA\n";
}
A& operator=(const A& a)
{
this->m_a = a.m_a;
this->m_b = a.m_b;
this->m_b = a.m_c;
// cout << "assignment\n";
return *this;
}
int m_a;
int m_b;
int m_c;
};
class B {
public:
B(A& b)
{
m_b=b;
cout << "constructB\n";
}
A m_b;
};
int main()
{
A a;
B b(a);
}
其运行结果为:
这是因为在类B中含有A类型的成员变量,在没有构造函数初始化列表的情况下,会在调用B的构造函数以前对成员变量m_b先调用A的构造函数,所以A的构造函数被调用了两次。
那么使用了构造函数初始化列表会怎么样?
class A {
public:
A()
: m_a(1)
, m_b(2)
, m_c(3)
{
cout << "constructA\n";
}
A& operator=(const A& a)
{
this->m_a = a.m_a;
this->m_b = a.m_b;
this->m_b = a.m_c;
// cout << "assignment\n";
return *this;
}
int m_a;
int m_b;
int m_c;
};
class B {
public:
B(A& b):m_b(b)
{
cout << "constructB\n";
}
A m_b;
};
int main()
{
A a;
B b(a);
}
运行结果为
可以看到A的构造函数只调用了一次,性能得到了提升。
此外,在使用构造函数初始化列表时,需要注意:构造函数初始化列表中的成员初始化顺序与成员变量在类中声明的顺序相同。这是因为成员变量的初始化顺序与它们在类中的声明顺序有关,而不是与它们在初始化列表中的顺序有关。
3.结论
总结起来,C++构造函数初始化列表提供了一种便捷的方式来初始化类的成员变量,可以提高代码效率和可读性。它适用于初始化普通成员变量、常量成员、引用成员和调用基类构造函数。通过正确使用构造函数初始化列表,可以确保对象在创建时以正确的状态初始化。