引子:我们知道,C++中类成员变量的初始化顺序与其在类中的声明顺序是有关的。

先看代码:

 class TestClass1
{
public:
TestClass1() {
cout << "TestClass1()" << endl;
}
TestClass1(const TestClass1&) { cout << "TestClass1(const TestClass1&)" << endl; }
TestClass1& operator=(const TestClass1&) { cout << "TestClas1s& operator=(const TestClass1&)" << endl; return *this; }
~TestClass1() {
cout << "~TestClass1()" << endl;
}
}; class TestClass2
{
public:
TestClass2() {
cout << "TestClass2()" << endl;
}
TestClass2(const TestClass2&) { cout << "TestClass2(const TestClass2&)" << endl; }
TestClass2& operator=(const TestClass2&) { cout << "TestClass2& operator=(const TestClass2&)" << endl; return *this; }
~TestClass2() {
cout << "~TestClass2()" << endl;
}
}; class Test
{
public:
Test() = default;
Test(TestClass1& tc1, TestClass2& tc2) :m_tc2(tc2), m_tc1(tc1){}
private:
TestClass1 m_tc1;
TestClass2 m_tc2;
};
 int main()
{
Test t;
}

程序结果为:

现象:先调用TestClass1的构造函数,再调用TestClass2的构造函数。

原因:在类Test中,m_tc1变量声明在m_tc2变量之前,故m_tc1在m_tc2之前初始化。

问题:在列表初始化的构造函数中,将m_tc2放在m_tc1之前,是否可以让m_tc2在m_tc1之前初始化?

代码设计

int main()
{
TestClass1 tc1;
TestClass2 tc2;
cout << "/**************************************************************************************/" << endl;
Test t(tc1, tc2);
}

运行结果为:

可以看到:仍然是TestClass1的构造函数先被调用,TestClass2的构造函数接着被调用。

结论:C++中类成员变量的初始化顺序与其在类中的声明顺序是有关的,而与其在初始化列表中的顺序无关。

再举一个例子:

然后我将代码写成这样:

 class Test
{
public:
Test() = default;
Test(TestClass1& tc1, TestClass2& tc2):m_tc2(tc2){}
private:
TestClass1 m_tc1;
TestClass2 m_tc2;
}; int main()
{
TestClass1 tc1;
TestClass2 tc2;
cout << "/**************************************************************************************/" << endl;
Test t(tc1, tc2);
}

注意与之前代码的差别:我们在初始化列表中只初始化了m_tc2,没有动m_tc1。

运行结果:

结果分析:在初始化Test的对象t时,由于m_tc1的声明顺序在m_tc2的声明顺序之前,所以t会想要先初始化m_tc1,但是它在初始化列表中没有找到初始化m_tc1的内容,于是它只好调用m_tc1的默认构造函数了,完成m_tc1的初始化后,再根据初始化列表中的内容初始化m_tc2。

C++中类成员变量在初始化列表中的初始化顺序的更多相关文章

  1. C++解析(12):初始化列表与对象构造顺序、析构顺序

    0.目录 1.类成员的初始化 2.类中的const成员 3.对象的构造顺序 3.1 局部对象的构造顺序 3.2 堆对象的构造顺序 3.3 全局对象的构造顺序 4.对象的析构顺序 5.小结 1.类成员的 ...

  2. Effective C++学习笔记:初始化列表中成员列出的顺序和它们在类中声明的顺序相同

    类成员的默认初始化顺序是按照声明顺序进行, 如果使用初始化列表初始化成员变量, 则必须按照成员变量的声明顺序进行; 否则, 在变量之间交替赋值时, 会产生, 未初始化的变量去赋值其他变量; 同时GCC ...

  3. C++中的初始化列表中可以对那些变量或对象进行初始化

    构造函数与其函数体之间可以添加初始化列表,能对某些对象进行初始化.格式为 类名() : 变量1(参数1),变量2(参数2) { } 1.     父类的对象的构造必须在初始化列表中,如: 子类名(): ...

  4. 【c++】构造函数初始化列表中成员初始化的次序性

    上代码 #include <iostream> using namespace std; class A { public: A(int v): j(v + 2), i(j) {} voi ...

  5. Java中类成员变量初始化顺序

    一. 定义处默认初始化vs构造函数中初始化 java中类成员变量支持在声明处初始化,也可以在构造函数中初始化,那么这两者有什么区别呢?看下面例子 public class FieldsInit { p ...

  6. 正确理解Widget::Widget(QWidget *parent) :QWidget(parent)这句话(初始化列表中无法直接初始化基类的数据成员,所以你需要在列表中指定基类的构造函数)

    最近有点忙,先发一篇我公众号的文章,以下是原文. /********原文********/ 最近很多学习Qt的小伙伴在我的微信公众号私信我,该如何理解下面段代码的第二行QWidget(parent) ...

  7. 【c++】必须在类初始化列表中初始化的几种情况

    转自:http://www.cnblogs.com/kaituorensheng/p/3477630.html 1. 类成员为const类型 2. 类成员为引用类型 #include <iost ...

  8. java中成员变量、代码块、构造函数运行顺序

    1.java虚拟机执行程序,首先须要装载类,安装现装载父类,初始化父类的静态代码块和静态成员变量 再load子类. 初始化子类静态代码块和成员变量 2.load完成父类与子类后,从main函数入口运行 ...

  9. Python3基础 list in/not in 判断一个变量是否在列表中存在

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

随机推荐

  1. C# Datatable 添加列

    DataTable dt = new DataTable("Datas"); DataColumn dc = null; //dt新增列 dc=dt.Columns.Add(&qu ...

  2. 使用redis的zset实现高效分页查询(附完整代码)

    一.需求 移动端系统里有用户和文章,文章可设置权限对部分用户开放.现要实现的功能是,用户浏览自己能看的最新文章,并可以上滑分页查看. 二.数据库表设计 涉及到的数据库表有:用户表TbUser.文章表T ...

  3. mysql时间类型和格式转换

    内容目录 简介mysql时间类型DATE_FORMAT()函数 简介 今天开发中,做一个功能需要对历史数据进行补充,相信大家也遇到过这样的情况,这个历史数据需要按月份和人的id进行区分,于是想到了my ...

  4. Robot Framework中对出错用例处理的策略

    出错后退出 在默认情况下,当一个测试用例中的某个关键字返回错误时,这个测试用例就停止执行剩余的关键字.RF会继续执行下一个用例.这么做的好处是节省时间--反正这里出问题要返回来看了,再继续执行剩下的关 ...

  5. git工作中总结

    # .克隆到本地 git clone url git clone -b 分支 url # 注意:克隆完成后,要删除.git隐藏文件夹 # .修改代码 # .生成master git init git ...

  6. 9.Java三大版本以及JDK,JRE,JVM简单介绍

    Write Once,Run Anywhere. JavaSE:标准版(桌面程序,控制台开发...),是Java的基础和核心. JavaME:嵌入式开发(手机,小家电...),现在基本不用已经过时. ...

  7. 如何在匿名thread子类中保证线程安全

    在做性能测试的过程中,我写了两个虚拟类ThreadLimitTimeCount和ThreadLimitTimesCount做框架,通过对线程的标记来完成超时请求的记录.旧方法如下: @Override ...

  8. if(a)是什么意思

    if(a)等价于 if(a!=0) if(!a)等价于 if(a==0)

  9. 机器学习-Tensorflow之Tensor和Dataset学习

    好了,咱们今天终于进入了现阶段机器学习领域内最流行的一个框架啦——TensorFlow.对的,这款由谷歌开发的机器学习框架非常的简单易用并且得到了几乎所有主流的认可,谷歌为了推广它的这个框架甚至单独开 ...

  10. octave在win上和linux上配置syms

    octave是类似matlab的一个科学计算工具集.需要用到积分.微分.求导的时候,需要连接python3的sympy. windows上先安装好python3,然后pip安装Sympy.具体过程: ...