首页 > 其他分享 >The Semantics of Constructors——2.4 成员初始化列表

The Semantics of Constructors——2.4 成员初始化列表

时间:2023-02-07 00:44:45浏览次数:40  
标签:初始化 String int 成员 Constructors list constructor Semantics 2.4

2.4 成员初始化列表(Member Initialization List)

当你写下一个constructor时,就有机会设定class members的初值。要不是经由member initialization list,就是在constructor函数本体之内。

1. 在下列情况下,为了让你的程序能够被顺利编译,你必须使用member initialization list:

  • 当初始化一个 reference member时; (引用成员)
  • 当初始化一个 const member时; (常量成员)
  • 当调用一个 base class的 constructor,而它拥有一组参数时;
  • 当调用一个 member class的 constructor,而它拥有一组参数时。

如何理解?

C++ primer: 如果成员是const、引用,或者属于某种未提供默认构造函数的类类型,我们必须通过构造函数初始值列表为这些成员提供初值。初始化const或者引用类型的数据成员的唯一机会就是通过构造函数初始值。

例如,

class ConstRef{
public:
    ConstRef(int ii);
private:
    int i;
    const int ci;
    int &ri;
};

ConstRef::ConstRef(int ii) {
    i = ii; //正确
    ci = ii; //错误:不能给const赋值
    ri = i; //ri没有被初始化
}

ConstRef::ConstRef(int ii):i(ii),ci(ii), ri(i){} //正确

2. 刚刚的第四种情况,程序可以被正确编译并执行,但是效率不高。

cpp primer: 初始化和赋值的区别: 在很多类中,初始化和赋值的区别事关底层效率问题。前者直接初始化数据成员,后者则先初始化再赋值。

除了效率问题外更重要的是,一些数据成员必须被初始化。建议读者养成使用构造函数初始值的习惯,这样能避免某些意想不到的编译错误,特别是遇到有的类含有需要构造函数初始值的成员时。

class Word {
    
    string _name;
    int _cnt;
public:
    //进行了赋值操作,没有使用member initialization list, 太初级了。
    Word() {
        _name = 0;
        _cnt = 0;
    }
};

在这里,Word constructor会先产生一个临时性的String object,然后将它初始化,之后以一个assignment运算符将临时性object指定给_name,随后再摧毁那个临时性object

以下是constructor可能的内部扩张结果:

//C++伪代码
Word::Word() {
    //调用String的default constructor
    _name.String::String();

    //产生临时对象
    String temp = String(0);

    //将temp每个成员都拷贝给_name
    _name.String::operator=(temp);

    //析构临时对象
    temp.String::~String();


    _cnt = 0;
}

一个明显更有效率的实现方法:

//使用初始化列表
Word::Word() : _name(0) {
    _cnt = 0;
}

它会被扩张成这样:

//C++伪代码
Word::Word() {
    //调用String(int) constructor
    _name.String::String(0);
    _cnt = 0;
}

3. member initialization list 中到底会发生什么事情?

许多C++新手对于list的语法感到迷惑,他们误以为它是一组函数调用。当然它不是!编译器会一一操作initialization list,以适当顺序在constructor之内安插初始化操作,并且在任何explicit user code之前。

4. 用一个成员初始化另一个成员

list中的项目顺序是由class中的members声明顺序决定的,不是由initialization list中的排列顺序决定的。

cpp primer 5th: 成员的初始化顺序与它们在类定义中的出现顺序一致:第一个成员先被初始化,然后第二个,以此类推。构造函数初始值列表中初始值的前后位置关系不会影响实际的初始化顺序。

因为initialization list的项目被放在explicit user code之前。


#include <iostream>
using namespace std;

class X{
public:
    int i;
    int j;
public:
    X(int val):j(val),i(j){} //意欲先初始化j,再用j初始化i,但实际由于i先于j声明,i(j)比j(val)先执行。
};

class Y{
public:
    int i;
    int j;
public:
    Y(int val):j(val){  //为了让j先初始化,应该这样写。
        i = j;
    }
};

int main(){
    X xx(1);
    Y yy(1);
    cout<<xx.i<<" "<<xx.j<<endl;  //4200347 1
    cout<<yy.i<<" "<<yy.j<<endl; //1 1
    return 0;
}

5.能否调用一个成员函数设定一个成员的初值?

Member function的使用是合法的(当然,我们必须不考虑它所用到的members是否已初始化),这是因为和此 object 相关的 this 指针已经被建构妥当,而constructor 大约被扩充为:

Global objects的内存保证会在程序启动的时候被清为0。Local objects配置于程序的堆栈中,heap objects 配置于自由空间中,都不一定会被清为0,它们的内容将是内存上次被使用后的遗迹。

标签:初始化,String,int,成员,Constructors,list,constructor,Semantics,2.4
From: https://www.cnblogs.com/qiangz/p/15997930.html

相关文章

  • The Semantics of Constructors——2.3 程序转化语意学
    2.3程序转化语意学#include"X.h"Xfoo(){Xxx;returnxx;}一个人可能会对代码做出以下假设:每次foo()被调用,就传回xx的值。如果classX定义了一个co......
  • 2.4总线操作和定时
    @目录一、引子二、介绍1.总线周期2.总线定时规范三、同步定时方式1.过程2.特点3.优缺点①优点②缺点四、异步定时方式1.介绍2.三种方式(1)不互锁方式(2)半互锁方式(3)全互锁方式3......
  • 2.4便于计算机处理的“补数”
    接下来我们就一起来看看表示负数的方法和右移的方法:二进制数中表示负数值时,一般会把最高位作为符号来使用,因此我们把这个最高位称为符号位。符号位是0时表示正数,符号位是1......
  • 每日算法--2023.2.4
    1.回文子串classSolution{publicintcountSubstrings(Strings){intres=0,n=s.length();for(inti=0;i<n;i++){intl......
  • 2023.2.4
    RondomRandomrd=newRandom();intnum=rd.nextInt();Enum(枚举)枚举是一种引用数据类型枚举类型怎么定义enum枚举类型名{枚举值1,枚举值2}结果只有2......
  • 三模鼠标中2.4G配对流程
                                       ......
  • 2.4章节检测
    P4587[FJOI2016]神秘数一道主席树的模板题我们先考虑暴力的做法,对于区间[l,r],我们先把里面的a[i]进行升序排序。设当前可以表示的数为[1,mx],对于要插入的数a[i],有两种可......
  • Mysql: 【Percona XtraBackup 2.4】 版的安装包 官方下载地址
    DownloadPerconaXtraBackup2.4https://www.percona.com/downloads/Percona-XtraBackup-2.4/Percona-XtraBackup-2.4.27/binary/tarball/ ......
  • 一步一步实现若依框架--2.4数据权限 data_scope
     1、点击若依的系统用户管理页面,测试各种数据权限生成的sql,若依调用的后台方法是:@DataScope(deptAlias="d",userAlias="u")publicList<SysUser>selectUser......
  • 行业领先的界面控件包 DevExpress v22.2.4 开年震撼发布
    DevExpressUniversal拥有.NET开发需要的所有平台控件,包含600多个UI控件、报表平台、DevExpressDashboardeXpressApp框架、适用于VisualStudio的CodeRush等一系列辅助......