问题描述
按照经验,设计一个类时需要对成员变量进行初始化。C++提供了两种初始化成员变量的途径,让程序员有了一些的选择空间。同时,这也给程序员留下了坑。
初始化类成员变量的途径:
- 在定义成员变量时初始化
- 在初始化成员列表中初始化
据此,设计以下代码:
#include <iostream>
using namespace std::literals;
std::string generate_name_1()
{
std::cout << "Calling generate_name_1() ..." << std::endl;
return "Alex"s;
}
std::string generate_name_2()
{
std::cout << "Calling generate_name_2() ..." << std::endl;
return "Brant"s;
}
std::string generate_name_3()
{
std::cout << "Calling generate_name_3() ..." << std::endl;
return "Chris"s;
}
class person_1
{
public:
person_1() = default;
std::string name() const { return m_name; }
private:
std::string m_name{ generate_name_1() };
};
class person_2
{
public:
person_2() :m_name{ generate_name_2() } {}
std::string name() const { return m_name; }
private:
std::string m_name;
};
class person_3
{
public:
person_3() :m_name{ generate_name_2() } {}
std::string name() const { return m_name; }
private:
std::string m_name{ generate_name_1() };
};
class person_4
{
public:
person_4() :m_name{ generate_name_2() }
{
m_name = generate_name_3();
}
std::string name() const { return m_name; }
private:
std::string m_name{ generate_name_1() };
};
int main()
{
std::cout << "===== class person_1 =====" << std::endl;
person_1 person1;
std::cout << person1.name() << std::endl;
std::cout << std::endl;
std::cout << "===== class person_2 =====" << std::endl;
person_2 person2;
std::cout << person2.name() << std::endl;
std::cout << std::endl;
std::cout << "===== class person_3 =====" << std::endl;
person_3 person3;
std::cout << person3.name() << std::endl;
std::cout << std::endl;
std::cout << "===== class person_4 =====" << std::endl;
person_4 person4;
std::cout << person4.name() << std::endl;
std::cout << std::endl;
return EXIT_SUCCESS;
}
上述代码的运行结果如下:
===== class person_1 =====
Calling generate_name_1() ...
Alex
===== class person_2 =====
Calling generate_name_2() ...
Brant
===== class person_3 =====
Calling generate_name_2() ...
Brant
===== class person_4 =====
Calling generate_name_2() ...
Calling generate_name_3() ...
Chris
我们看到:
- 如果定义成员变量时初始化,则使用此处的初始化值
- 如果在初始化成员列表中初始化,则使用此处的初始化值
- 如果定义成员变量时初始化,并且同时在初始化成员列表中初始化,则定义成员变量时的初始化被忽略
- 如果在构造函数的函数体内给成员变量赋值,则该已被初始化的成员变量的值在此处被赋值。
总的来说就是:赋值会覆盖初始化值,初始化成员列表中的初始化会覆盖定义成员变量时的初始化。
总结
- 最好对所有的类成员变量进行初始化,以防止其值处于不确定的状态。
- 基础且通用的初始化值应该在定义类成员变量时进行初始化,而较为特殊的初始化值应该在构造函数的初始化成员列表中进行初始化。
- 最好不要在构造函数中,试图通过赋值的方式对成员变量进行初始化。因为这样会多出赋值的过程,降低程序的性能。