c++类初始化列表初探
时间:2020-04-22
本文章向大家介绍c++类初始化列表初探,主要包括c++类初始化列表初探使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
1 初始化和赋值
- 初始化:创建一个对象并赋予一个初值;
- 赋值:通过赋值运算符(=),将“=”右侧值赋给“=”左侧对象;
int a=5; //创建一个int对象a,初始值为5
a=12; //赋值
对于内置数据类型,初始化和赋值的区别不大;
对于自定义类型,初始化操作调用拷贝构造函数,赋值操作调用拷贝赋值运算符,下面以Person类为例;
//Person类
class Person {
public:
Person()
{
cout << "Person 默认构造调用" << endl;
}
Person(const char *name,int age)
{
cout << "Person有参构造调用" << endl;
this->m_Name = new char[strlen(name) + 1];
strcpy_s(this->m_Name, strlen(name) + 1, name);
this->m_Age = age;
}
Person(const Person&p)
{
cout << "Person 拷贝构造调用" << endl;
if (this->m_Name != NULL)
{
delete[]this->m_Name;
this->m_Name = NULL;
}
this->m_Name = new char[strlen(p.m_Name) + 1];
strcpy_s(this->m_Name,strlen(p.m_Name)+1, p.m_Name);
this->m_Age = p.m_Age;
}
Person&operator=(const Person &p)
{
cout << "Person拷贝赋值" << endl;
if (this->m_Name != NULL)
{
delete[]this->m_Name;
this->m_Name = NULL;
}
this->m_Name = new char[strlen(p.m_Name) + 1];
strcpy_s(this->m_Name, strlen(p.m_Name) + 1, p.m_Name);
this->m_Age = p.m_Age;
return *this;
}
void showInfo()
{
cout << this->m_Name << "今年" << this->m_Age << "岁!" << endl;
}
~Person()
{
cout << "Person析构调用" << endl;
if (m_Name != NULL)
{
delete[]m_Name;
m_Name = NULL;
}
}
char* m_Name;
int m_Age;
};
//测试函数
void test()
{
Person p("小明", 23);
p.showInfo();
cout<<endl;
Person p2(p);//也可写为Person p2=p,初始化
p2.showInfo();
cout<<endl;
Person p3;
p3 = p;//赋值
p3.showInfo();
cout<<endl;
}
运行结果
1.1 结论
通过程序运行结果可以知道,Person p2(p)语句调用类的拷贝构造函数,由于Person类中的m_Name是指向堆区空间的数据,所以我们必须提供自定义的拷贝构造函数,因为默认的拷贝构造函数只是简单的值拷贝;p3 = p语句调用类的拷贝赋值,同理编译器会提供一个默认的拷贝赋值运算符,也是简单的值拷贝,所以我们必须提供自定义的拷贝赋值运算符;
2 构造函数初始化列表
我们知道,构造函数是用来初始化类对象的数据成员,编写构造函数一般有两种方式,一种是通过在函数体里赋值实现,另一种是通过初始值列表,对于内置数据类型,这两种方式的相差无几,但是如果该类的数据成员有自定义的类型,那么就效率上讲,两者有些差别;
class MyClass1 {
public:
MyClass1()
{
cout << "myclass1 默认构造调用" << endl;
}
MyClass1(const MyClass1 &)
{
cout << "myclass1 默认拷贝构造调用" << endl;
}
MyClass1&operator=(const MyClass1 &)
{
cout << "myclass1 默认拷贝赋值调用" << endl;
return *this;
}
};
class MyClass2 {
public:
MyClass2(int a,MyClass1 &c)
{
this->m_A = a;
this->m_class = c;
}
//MyClass2(int a,MyClass1&c):m_A(a),m_class(c){}
int m_A;
MyClass1 m_class;
};
//测试函数
void test()
{
MyClass1 my1;
MyClass2 my2(3, my1);
}
运行结果
- 使用函数体内赋值
- 使用初始化列表
2.1 结论
通过运行结果可以知道对于自定义类型,通过初始化列表进行初始化,只需调用一次拷贝构造函数,而在构造函数中初始化,需要调用一次默认构造函数和一次赋值操作。
3 必须使用初始化列表的情况
如果类的数据成员是const,引用或者某种未提供默认构造函数的类类型,那么我们必须通过构造函数初始值列表为这些成员提供初值(c++prime第五版)
3.1 结论
建议养成使用构造函数初始值的习惯,这样能避免某些意想不到的编译错误
4 成员初始化顺序
构造函数初始值列表只说明用于初始化成员的值,并不限定初始化的具体顺序,成员的初始化顺序与它们在类定义中出现的顺序一致
class MyClass {
public:
MyClass(MyClass2 m2, MyClass3 m3, MyClass4 m4) :mc3(m3), mc4(m4), mc2(m2) {}//这里的顺序并不影响mc2,mc3,mc4的初始化顺序
//由下面出现的顺序决定,所以成员初始化顺序为:mc2->mc3->mc4
MyClass2 mc2;
MyClass3 mc3;
MyClass4 mc4;
};
5 参考资料
原文地址:https://www.cnblogs.com/woshidaan-caw/p/12751774.html
- 斐波那契额数列及青蛙跳台阶问题
- 在Mac OS X上配置Apache2
- 合并两个排序的链表
- 还有5天,你的比特币最重要的孩子UB-UBTC 可能就永远不属于你了
- Spark SQL 用户自定义函数UDF、用户自定义聚合函数UDAF 教程(Java踩坑教学版)
- Webpack多入口文件、热更新等体验
- 从hello world 解析程序运行机制
- 万达大量员工“被”辞职?曲德君回应:万达网科没有倒
- iOS Programming – 触摸事件处理(2)
- 洋葱海外仓融资2亿元 官网启用msyc.cc域名
- Webpack单元测试,e2e测试
- [看图说话] 基于Spark UI性能优化与调试——初级篇
- Unix下c程序内存泄露检测工具
- 查找链表中倒数第k个结点
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- AkShare-另类数据-彭博亿万富豪指数
- AkShare-股票数据-券商业绩月报
- AkShare-期货数据-仓单日报-上海期货交易所
- AkShare-期货数据-仓单日报-大连商品交易所
- AkShare-期货数据-仓单日报
- AkShare-股票数据-美港目标价
- AkShare-Websocket-行情数据
- AkShare-股票-市场总貌
- AkShare-使用教程-R语言调用数据接口
- AkShare-重要机构-美国商品期货交易委员会
- AkShare-重要机构-伦敦金属交易所
- 为什么不推荐使用BeanUtils属性转换工具
- 从源码打造云原生时代的「Linux」——Kubernetes
- Django-models & QuerySet API
- [奇淫巧技]GitHub个人页的新玩法