前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++:20---成员变量初始化方式

C++:20---成员变量初始化方式

作者头像
用户3479834
发布2021-02-03 15:44:40
1.8K0
发布2021-02-03 15:44:40
举报
文章被收录于专栏:游戏开发司机游戏开发司机

成员变量初始化有三种方式:

  • 在构造函数体内赋值初始化
  • 在自定义的公有函数体中赋值初始化(一般用于成员变量的初始化)
  • 在构造函数的成员初始化列表初始化

一、构造函数体内初始化

  • 说明:在构造函数体内的初始化方式,本质是是为成员变量赋值,而不是真正意义上的初始化,这点要特别注意!(下面介绍成员初始化列表时会有演示案例对比说明)
代码语言:javascript
复制
class Cperson
{
private:
int m_age;
float m_height;
char* m_name;
public:
Cperson(int age,float height,const char* name)
{
m_age=age;
m_height=height;
if(m_name)//先判断当前是否为空
delete[]  m_name;
if(name)//如果外部传入的不为空
{
int len=strlen(name);
m_name=new char[len+1];//创建内存
strcpy(t m_name,name);
}
else
m_name=nullptr;
}
}

二、自定义的公有函数体中赋值初始化

  • 说明:与构造函数体内初始化方式一样,此种方式本质上也是赋值,而不是初始化
代码语言:javascript
复制
class Cperson
{
private:
int m_age;
float m_height;
char* m_name;
public:
void setPerson(int age,float height,const char* name)
{
m_age=age;
m_height=height;
if(m_name)//先判断当前是否为空
delete[]  m_name;
if(name)//如果外部传入的不为空
{
int len=strlen(name);
m_name=new char[len+1];//创建内存
strcpy(t m_name,name);
}
else
m_name=nullptr;
}
}

三、成员初始化列表初始化

  • 特点:
    • 初始化顺序与书写的在构造函数后的顺序无关,而与成员变量的定义顺序有关(下面有演示案例)
    • 初始化列表初始化优先于构造函数内的代码执行顺序
    • 写在构造函数的后面,随着构造函数的执行而执行
    • 初始化顺序:
    • 多个成员之间用逗号隔开,括号内为形参
    • 一般只对无动态内存的成员、const成员、引用初始化(const成员、引用成员必须在初始化列表初始化)
    • 成员初始化列表初始化效率更高(下面有演示案例)
    • 有动态内存的成员必须在构造函数内部进行初始化(为什么?因为动态内存不能进行简单的赋值,因此所存在的地址不同,要自己申请动态内存并初始化)。牢记:内部数据内部处理,外部数据外部处理
代码语言:javascript
复制
class Cperson
{
private:
int m_age;
float m_height;
char* m_name;
public:
Cperson(int age,float height,const char* name);
}
//m_name为指针类型,需要自己申请空间
Cperson::Cperson(int age,float height,const char* name):m_age(age),m_height(height)
{
if(m_name)//先判断当前是否为空
delete[]  m_name;
if(name)//如果外部传入的不为空
{
int len=strlen(name);
m_name=new char[len+1];//创建内存
strcpy(m_name,name);
}
else
m_name=nullptr;
}

成员的初始化顺序

  • 成员初始化的顺序,与在构造函数后面书写的顺序无关。而与成员变量定义的顺序有关
  • 例如下面的代码,在构造函数花括号后m_height放在m_age前面,但是先初始化m_age再初始化m_height,因为m_age先定义
代码语言:javascript
复制
class Cperson
{
private:
int m_age;
float m_height;
public:
Cperson(int age,float height);
}
Cperson::Cperson(int age,float height):m_height(height),m_age(age)
{}

错误事例(初始化顺序导致的错误)

  • 一个特殊情况:如果用一个成员变量去初始化另一个成员变量,就要注意初始化顺序了
  • 因此,我们在初始化的时候,尽量避免用某些成员去初始化另一个成员
代码语言:javascript
复制
//下面代码中,i先被初始化,但是i是根据j初始化的,但j后初始化,就会产生不好的后果
class X
{
int i;
int j;
public:
X(int value):j(value),i(j)
{}
};
  • 更正:因为初始化列表初始化比构造函数内初始化早,所以可以将上面的代码改为下面的形式就不会出错了
代码语言:javascript
复制
class X
{
int i;
int j;
public:
//j先初始化,i再初始化
X(int value):j(value)
{
i(j);
}
};

错误事例(针对const成员与引用成员)

  • 此案例强调是的,const成员和引用必须在成员初始化列表进行初始化
代码语言:javascript
复制
class Person
{
private:
const int id;
int& m_id;
public:
Person(int i);
};
Person::Person(int i)
{
id=i;//错误,const成员变量必须在成员初始化列表初始化
m_id=id;//错误,引用也必须在成员初始化列表初始化
}

演示案例(成员初始化列表初始化效率更高)

  • 例如下面在构造函数内对两个成员进行初始化
代码语言:javascript
复制
class Word{
string _name;
int _cnt;
public:
Word(){
_name=0;//先创建一个临时string对象,赋值为0,然后拷贝给_name
_cnt=0;
//构造函数结束之后,临时对象析构释放
}
};
  • 但是如果使用下面的成员初始化列表初始化,那么就省去了创建临时对象再拷贝的过程,因此成员初始化列表初始化的效率更高
代码语言:javascript
复制
class Word{
string _name;
int _cnt;
public:
Word():_name(0),_cnt(0){} //直接初始化_name,不创建临时对象
};

四、初始化方式总结

  • 根据上面的三种方式,总结出:成员初始化列表初始化成员才是真正意义上的初始化,其他两种方式都是为赋值
  • 初始化和赋值涉及到底层效率的问题:初始化是直接初始化。而赋值是先初始化一个临时变量,再赋值。前者效率高
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-12-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 游戏开发司机 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 成员变量初始化有三种方式:
  • 一、构造函数体内初始化
  • 二、自定义的公有函数体中赋值初始化
  • 三、成员初始化列表初始化
    • 成员的初始化顺序
      • 错误事例(初始化顺序导致的错误)
        • 错误事例(针对const成员与引用成员)
          • 演示案例(成员初始化列表初始化效率更高)
          • 四、初始化方式总结
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档