成员初始化列表是C++中初始化类成员变量的一种更高效的方式。它在构造函数体执行之前就完成了成员变量的初始化,避免了先构造再赋值的性能开销。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
class Example
{
public:
Example()
{
std::cout << "Create Example" << std::endl;
}
Example(int x)
{
std::cout << "Create Example with " << x << std::endl;
}
};
class Entity
{
private:
std::string m_Name;
Example m_Example;
public:
// 传统初始化方式 - 先构造,再赋值
Entity()
{
m_Name = "Unknown"; // 这是赋值,不是初始化
m_Example = Example(8); // 这会创建临时对象,然后赋值
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class Entity
{
private:
std::string m_Name;
Example m_Example;
public:
// 使用成员初始化列表 - 直接初始化
Entity() : m_Name("Unknown"), m_Example(Example(8)) {}
Entity(const std::string& name, const Example& example)
: m_Name(name), m_Example(example) {}
const std::string& GetName() const { return m_Name; }
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class PerformanceTest
{
private:
std::string m_Data;
public:
// 方式1:构造函数体内赋值
PerformanceTest(const std::string& data)
{
m_Data = data; // 先调用默认构造函数,再调用赋值操作符
}
// 方式2:成员初始化列表
PerformanceTest(const std::string& data) : m_Data(data)
{
// 直接调用拷贝构造函数,更高效
}
};
|
1
2
3
4
5
6
7
8
9
10
11
|
class ConstMember
{
private:
const int m_Value;
public:
// const成员必须在初始化列表中初始化
ConstMember(int value) : m_Value(value) {}
// 错误:const成员不能在构造函数体内赋值
// ConstMember(int value) { m_Value = value; } // 编译错误
};
|
1
2
3
4
5
6
7
8
9
10
11
|
class ReferenceMember
{
private:
int& m_Ref;
public:
// 引用成员必须在初始化列表中初始化
ReferenceMember(int& ref) : m_Ref(ref) {}
// 错误:引用不能在构造函数体内赋值
// ReferenceMember(int& ref) { m_Ref = ref; } // 编译错误
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
class NoDefaultConstructor
{
public:
NoDefaultConstructor(int value) {} // 只有带参构造函数
// 没有默认构造函数
};
class Container
{
private:
NoDefaultConstructor m_Member;
public:
// 必须使用初始化列表
Container() : m_Member(42) {}
// 错误:m_Member没有默认构造函数
// Container() { m_Member = NoDefaultConstructor(42); } // 编译错误
};
|
成员变量的初始化顺序由它们在类中的声明顺序决定,而不是初始化列表中的顺序:
1
2
3
4
5
6
7
8
9
10
11
12
|
class InitOrder
{
private:
int m_First; // 第一个被初始化
int m_Second; // 第二个被初始化
public:
// 即使初始化列表的顺序不同,仍按声明顺序初始化
InitOrder() : m_Second(2), m_First(1) {}
// 建议:保持初始化列表顺序与声明顺序一致
InitOrder(int a, int b) : m_First(a), m_Second(b) {}
};
|
- 成员初始化列表要比在构造函数体内赋值更高效,应该优先使用成员初始化列表
- 初始化顺序:成员变量按照在类中的声明顺序进行初始化,而不是初始化列表中的顺序
- 必须使用场景:const成员、引用成员、没有默认构造函数的成员对象
- 最佳实践:总是使用成员初始化列表,保持列表顺序与声明顺序一致