C++的成员构造函数初始化列表:构造函数中初始化类成员的一种方式,当我们编写一个类并向该类添加成员时,通常需要某种方式对这些成员变量进行初始化。
建议应该在所有地方使用成员初始化列表进行初始化
成员初始化的方法
方法一:
正常使用{}赋值类成员变量
cpp
class Entity
{
private:
string m_Name; // 第一种方法会在这使用一次默认构造函数Entity()
int m_Score;
Example m_example;
public:
//第一种方法初始化
//默认构造函数
Entity()
{
m_Name = "Unknown"; // 第一种方法在构造函数时会调用两次默认构造函数
}
//构造函数:接受name作为参数的构造函数
Entity(const string& name)
{
m_Name = name;
}
};
方法二:
使用成员初始化列表方式
形式就是函数名后面加上冒号,对成员变量进行赋值,用括号替换等号
cpp
class Entity
{
private:
string m_Name;
int m_Score;
Example m_example;
public:
Entity()
: m_example(Example(8)) // m_example(8)等价于m_example(Example(8))
{
//m_example = Example(8);
}
// 成员初始化列表方式
// 注意:不管你怎末写初始化列表,它都会按照定义类成员的顺序进行初始化,因此要确保做成员初始化列表时,要与成员变量声明时的顺序一致
Entity(const int score)
: m_Name("Unknown"),m_Score(score) // 列出想要初始化的成员,等价m_Name = "Unknown";
{
}
Entity(const string& Name,const int& score)
: m_Name(Name),m_Score(score) // 用括号替换等号,等价m_Name = name;
{
}
const string& GetName() const
{
return m_Name;
}
};
注意:不管你怎末写初始化列表,它都会按照定义类成员的顺序进行初始化,因此要确保做成员初始化列表时,要与成员变量声明时的顺序一致。成员变量声明时按照m_Name,m_Score顺序,使用成员初始化列表时需要同声明顺序一致。
两种方法的差别:
在特定类,两者功能上有区别
第一种方法在构造函数时会调用两次默认构造函数
案例:
cpp
# include <iostream>
# include <string>
using namespace std;
class Example
{
public:
Example()
{
cout << "Created Entity!" << endl;
}
Example(int x)
{
cout << "Created Entity with " << x << "!" << endl;
}
};
class Entity
{
private:
string m_Name; // 第一种方法会在这使用一次默认构造函数Entity()
int m_Score;
Example m_example;
public:
//在特定类,两者功能上有区别
//第一种方法初始化
//默认构造函数
Entity()
{
m_Name = "Unknown"; // 第一种方法在构造函数时会调用两次默认构造函数
m_example = Example(8);
}
};
int main()
{
Entity e0;
//cout << e0.GetName() << endl;
/*Entity e1("Chen");
cout << e1.GetName() << endl;*/
cin.get();
return 0;
}
输出结果会同时打印出Created Entity! 以及 Created Entity with 8!。由于string是一个类,因此在声明变量时就会调用默认构造函数Entity(),而在实例化对象中,也会调用一次构造函数,然后丢弃第一次的字符串,造成资源的浪费。
当使用成员初始化列表方式就不会出现这种问题。
cpp
Entity()
: m_example(Example(8)) // m_example(8)等价于m_example(Example(8))
{
m_Name = "Unknown"; // 第一种方法在构造函数时会调用两次默认构造函数
//m_example = Example(8);
}
总的来说:应该在所有地方使用成员初始化列表进行初始化,要不然会浪费性能,对于整型这样的基本类型,它不会被初始化,除非你通过赋值来初始化它们
整体代码:
cpp
# include <iostream>
# include <string>
using namespace std;
class Example
{
public:
Example()
{
cout << "Created Entity!" << endl;
}
Example(int x)
{
cout << "Created Entity with " << x << "!" << endl;
}
};
class Entity
{
private:
string m_Name; // 第一种方法会在这使用一次默认构造函数Entity()
int m_Score;
Example m_example;
public:
//在特定类,两者功能上有区别
//第一种方法初始化
//默认构造函数
Entity()
: m_example(Example(8)) // m_example(8)等价于m_example(Example(8))
{
m_Name = "Unknown"; // 第一种方法在构造函数时会调用两次默认构造函数
//m_example = Example(8);
}
//构造函数:接受name作为参数的构造函数
Entity(const string& name)
{
m_Name = name;
}
// 成员初始化列表方式
// 注意:不管你怎末写初始化列表,它都会按照定义类成员的顺序进行初始化,因此要确保做成员初始化列表时,要与成员变量声明时的顺序一致
Entity(const int score)
: m_Name("Unknown"),m_Score(score) // 列出想要初始化的成员,等价m_Name = "Unknown";
{
}
Entity(const string& Name,const int& score)
: m_Name(Name),m_Score(score) // 用括号替换等号,等价m_Name = name;
{
}
const string& GetName() const
{
return m_Name;
}
};
int main()
{
Entity e0;
//cout << e0.GetName() << endl;
/*Entity e1("Chen");
cout << e1.GetName() << endl;*/
cin.get();
return 0;
}
// 应该在所有地方使用成员初始化列表进行初始化,要不然会浪费性能,对于整型这样的基本类型,它不会被初始化,除非你通过赋值来初始化它们