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 参考资料
c++类初始化列表初探的更多相关文章
- 【c++】必须在类初始化列表中初始化的几种情况
转自:http://www.cnblogs.com/kaituorensheng/p/3477630.html 1. 类成员为const类型 2. 类成员为引用类型 #include <iost ...
- C++类初始化列表
转自:https://www.cnblogs.com/BlueTzar/articles/1223169.html 构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟 ...
- C++:四种必须使用初始化列表情况
[c++]必须在类初始化列表中初始化的几种情况 1. 类成员为const类型 2. 类成员为引用类型 复制代码 #include <iostream> using namesp ...
- C++-什么时候需要在类的构造函数中使用初始化列表
1,如果基类没有default构造函数,则意味着其不能自己初始化.如果其被派生,派生类的构造函数要负责调用基类的构造函数,并传递给它需要的参数.下例中Base 2,如果类成员没有默认构造函数.下例中E ...
- C++类构造函数初始化列表
C++类构造函数初始化列表 构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式.例如: class CExample {public: ...
- C++类的成员初始化列表的相关问题
在以下四中情况下,要想让程序顺利编译,必须使用成员初始化列表(member initialization list): 1,初始化一个引用成员(reference member): 2,初始化一个常量 ...
- Effective C++学习笔记:初始化列表中成员列出的顺序和它们在类中声明的顺序相同
类成员的默认初始化顺序是按照声明顺序进行, 如果使用初始化列表初始化成员变量, 则必须按照成员变量的声明顺序进行; 否则, 在变量之间交替赋值时, 会产生, 未初始化的变量去赋值其他变量; 同时GCC ...
- c++ 关于类构造函数的初始化列表
除了性能问题之外,有些时场合初始化列表是不可或缺的,以下几种情况时必须使用初始化列表 常量成员,因为常量只能初始化不能赋值,所以必须放在初始化列表里面 引用类型,引用必须在定义的时候初始化,并且不能重 ...
- C++: 类成员初始化列表语法
类的成员初始化列表的初始化的基本语法,类的构造函数还可以运用此语法为其变量初始化: class Class { private: int a; int b; char ch; public: Cl ...
随机推荐
- Java中Comparable和Comparator的区别
前言 最近复习遇到了这个问题,在此进行一个详细的记录,分享给大家. 两个接口的区别 包区别 Comparable接口是在java.lang下. Comparator接口是在java.util下. 使用 ...
- pycharm创建虚拟环境venv和添加依赖库package
1.创建虚拟环境 因为项目采用不同版本的python,所依赖的库的版本也不一样,为了避免版本冲突,为每一个项目每个python版本创建一个虚拟环境,环境中所使用的依赖库也是独立存在,不会被其他版本或其 ...
- python txt文件批处理
首先,切换文件路径到所在文件夹 然后,将txt文件内容按行读取,写入到all.txt def txtcombine(): files=glob.glob('*.txt') all = codecs.o ...
- [LeetCode] 935. Knight Dialer 骑士拨号器
A chess knight can move as indicated in the chess diagram below: . This time, we place o ...
- ArrayList的传值问题
ArrayList是一个对象类型,记录一下遇到的传值问题 假设两个ArrayList类型的值a和b,a有值,b无值,想把a的值全部复制给b. 如果使用 b = a; 进行赋值,会将a的地址赋值给b,当 ...
- 一文综述python读写csv xml json文件各种骚操作
Python优越的灵活性和易用性使其成为最受欢迎的编程语言之一,尤其是对数据科学家而言.这在很大程度上是因为使用Python处理大型数据集是很简单的一件事情. 如今,每家科技公司都在制定数据战略. ...
- coding++:MySQL-ERROR:Column 'complaint_settlement_id' in field list is ambiguous
(多表查询出现的问题)列'ID'在字段列表中重复,其实就是两张表有相同的字段,但是使用时表字段的名称前没有加表名,导致指代不明. 如 前面加上表名前缀就没问题了.
- Springcloud config + zuul 搭建动态网关
1,实现的效果,就是zuul 网关的配置路由实现负载均衡,zuul 的配置文件放在springcloud config 上 2,需要的服务如下: 3,其实就是配置下springcloud-zuul 的 ...
- pycharm 2.7 快捷键
提示 CTRL Q: 在参数列表位置,显示可以输入的所有参数 CTRL Q: 查看选中方法的文档字符串 阅读 CTRL -: 折叠当前代码 CTRL +: 展开当前代码 CTRL SHIFT -: 折 ...
- 一文读懂什么是CA证书
Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE /* Style Definitions */ table.MsoNormalTable ...