如何在构造函数中初始化成员变量(C++构造函数初始化列表注意的坑)
原文链接:https://www.zhoubotong.site/post/87.html
之所以写这篇文章 ,是觉得里面有些细节如果不注意 ,很容易出错或踩坑 ,网上有很多教程对这块的描述部分存在错误 。希望下面的介绍能给大家带来帮助 。大家知道当我们需要初始化类中的成员变量时 ,除了可以直接在构造函数里面进行直接赋值 ,还可以使用初始化列表的方式来对成员变量进行初始化。
提到这里 ,顺便说下什么是构造函数初始化列表 。
C++初始化列表
语法
Contructor(type1 var1, type2 var2): m_var1(var1), m_var2(var2) { }参数
属性 描述 type1 形参 var1 的类型 。 var1 形参 var1 。 type2 形参 var2 的类型 。 var2 形参 var2 。 m_var1 成员变量 m_var1 。 m_var2 成员变量 m_var2 。说明
我们使用初始化列表的方式 ,用形参 var1 初始化了成员变量 m_var1 ,用形参 var2 初始化了成员变量 m_var2 。举个例子:
#include <iostream> using namespace std; class Student { private: char *m_name; int m_age; float m_score; public: Student(char *name, int age, float score); void show(); }; // 采用初始化列表 Student::Student(char *name, int age, float score) : m_name(name), m_age(age), m_score(score) { // TODO } void Student::show() { cout << m_name << " age is " << m_age << "score is " << m_score << endl; } int main() { Student stu((char *)"鸠摩智", 28, 5); stu.show(); Student *pstu = new Student((char *)"慕容复", 27, 86); // 使用指针对象 new 实例化 pstu->show(); return 0; }上面的例子定义构造函数时并没有在函数体中对成员变量赋值 ,而是在函数首部与函数体之间添加了一个冒号:,后面紧跟m_name(name), m_age(age), m_score(score)语句 ,
可以理解成相当于函数体内部的m_name = name; m_age = age; m_score = score;也是赋值的意思 。
注意:使用构造函数初始化列表并没有效率上的优势 ,仅仅是书写方便,当成员变量较多时这种写法非常简洁。下面重点说下需要注意的地方:
初始化列表可以用于全部成员变量 ,也可以只用于部分成员变量 。什么意思?比如我们只对 m_name 使用初始化列表 ,其他成员变量还是=赋值: // 采用初始化列表 Student::Student(char *name, int age, float score) : m_name(name) { // 只用于部分成员变量 m_age = age; m_score = score; }输出结果是一样的 。 注意!注意!注意!,成员变量的初始化顺序与初始化列表中列出的变量的顺序无关 ,它只与成员变量在类中声明的顺序有关。
请大家仔细看下面的代码: #include <iostream> using namespace std; class Student { private: int m_age; float m_score; public: Student(float s); void show(); }; Student::Student(float s) : m_score(s), m_age(m_score) {} //注意这里:我们将m_score放在了m_age的前面 ,看起来是先给m_score赋值 ,再给m_age赋值(m_age=m_score) ,其实不是的 void Student::show() { cout << m_age << ", " << m_score << endl; } int main() { Student stu(99); stu.show(); return 0; }结论
所以成员变量的赋值顺序由它们在类中的声明顺序决定 ,在 上面的Student 类中 ,我们先声明的 m_age ,再声明的 m_score ,
给 m_age 赋值时 ,m_score 还未被初始化,所以输出的m_age的值是默认类型的0;给 m_age 赋值完成后才给m_score 赋值 ,此时 m_score 的值才是99 。
如果大家对上面理解了 ,我们再看下面的代码,大家可以猜下输出啥? #include <iostream> using namespace std; class Student { private: int m_age; float m_score; public: Student(float s); void show(); }; Student::Student(float s) : m_score(s), m_age(m_score) { m_age = m_score; m_score = s; } void Student::show() { cout << m_age << ", " << m_score << endl; } int main() { Student stu(99); stu.show(); return 0; }输出:99, 99 ,大家请细品!写到最后再提下:构造函数初始化列表还有一个很重要的作用
,那就是初始化 const 成员变量 。
网上很多教程说初始化 const 成员变量的唯一方法就是使用初始化列表。这是错误的,描述的不够严谨 ,为什么这样说 ,我们来看网上很多教程的例子: #include <iostream> using namespace std; class Student { public: Student(string name, int age) { m_name = name; m_age = age; } void show(); private: const string m_name; int m_age; }; void Student::show() { cout << m_name << ", " << m_age << endl; } int main() { Student stu("鸠摩智", 28); stu.show(); Student stu1("慕容复", 27); stushow(); return 0; }输出:
于是网上很多教程说只能使用初始化列表的方式 ,来进行初始化 ,现在 ,按照网上的说法修改程序如下: #include <iostream> using namespace std; class Student { public: Student(string name, int age) : m_name(name), m_age(age) {} void show(); private: const string m_name; int m_age; }; void Student::show() { cout << m_name << ", " << m_age << endl; } int main() { Student stu("鸠摩智", 28); stu.show(); Student stu1("慕容复", 27); stushow(); return 0; }这次在构造函数上面 ,使用了初始化列表的方式 ,初始化了 const 成员变量 ,这次程序没有报错 ,因此,const 成员变量只可以使用初始化列表的方式进行初始化( 误人) 。
这个描述是错误的 ,并不是const 成员变量只能使用初始化列表 。在构造函数里面初始化赋值是没有任何问题的 。
针对上面的问题我们来改下代码 。注意这里只是改变了m_name的数据类型为指针型 。 #include <iostream> using namespace std; class Student { public: Student(char *name, int age) { // 使用构造方法初始化赋值 m_name = name; m_age = age; } void show(); private: const char *m_name; // 注意这里是指针变量的常量 int m_age; }; void Student::show() { cout << m_name << ", " << m_age << endl; } int main() { Student stu((char *)"鸠摩智", 28); stu.show(); Student stu1((char *)"慕容复", 27); stushow(); return 0; }所以类中对于const 修饰 ,既可以使用初始化列表的方式赋值,也可以使用构造函数的方式赋值 。
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!