栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++初始化列表

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++初始化列表

定义
使用初始化列表的原因
必须使用初始化列表的时候
成员变量的顺序

链接添加链接描述

这里对列表初始化做个总结:
类中的成员变量只是一个声明,真正的定义在列表初始化,即使你不写列表初始化,默认有一个列表初始化。

如果你不使用列表初始化,在构造函数内部对成员变量进行赋值,那么其实就是构造函数,然后使用赋值运算。
具体我们来看下面的这个例子:

class Test1 {
public:
  Test1() // 无参构造函数
  {
    std::cout << "Construct Test1" << std::endl;
  }
  Test1(const Test1 &t1) // 拷贝构造函数
  {
    std::cout << "Copy constructor for Test1" << std::endl;
    this->a = t1.a;
  }
  Test1 &operator=(const Test1 &t1) // 赋值运算符
  {
    std::cout << "assignment for Test1" << std::endl;
    this->a = t1.a;
    return *this;
  }
  int a;
};

class Test2 {
public:
  Test1 test1;
  Test2() {}
  Test2(Test1 &t1) { test1 = t1; }
  // Test2(Test1 &t1) : test1(t1) {}
};

int main() {
  Test1 test1;
  Test2 test2(test1);
  }

我们先看无初始化列表的打印情况:

Construct Test1
Construct Test1
assignment for Test1

这里出现了两次无参构造和一次赋值运算,为什么会出现两次无参构造呢?
这是因为Test2使用默认的初始化列表对test1进行空间分配,调用了一次,然后又调用了一次拷贝构造,再加上上面Test1本身的一次,所以出现了两次无参构造。

这次我们将Test2改一下:

class Test2 {
public:
  Test1 test1;
  Test2() {}
  
  Test2(Test1 &t1) : test1(t1) {}
};

再次执行一次上面的main函数:

Construct Test1
Copy constructor for Test1

这次只有一次无参构造,一次拷贝构造,这是因为这次用的是初始化列表,初始化列表中直接调用拷贝构造一次成形。

我们再次改动一下,将class Test2 恢复到构造函数内赋值,并且取消class Test1中的无参数构造函数,按照上面讲的,class Test2会在默认的初始化列表中调用class Test1的无参数构造(但是这次我们删除了class Test1的无参数构造,那么调用无参数构造的话就会一定失败报错),按照这个假设,我们实验一下:

class Test1 {
public:
  //Test1() // 无参构造函数
  //{
  //  std::cout << "Construct Test1" << std::endl;
  //}
  Test1(const Test1 &t1) // 拷贝构造函数
  {
    std::cout << "Copy constructor for Test1" << std::endl;
    this->a = t1.a;
  }
  Test1 &operator=(const Test1 &t1) // 赋值运算符
  {
    std::cout << "assignment for Test1" << std::endl;
    this->a = t1.a;
    return *this;
  }
  int a;
};

class Test2 {
public:
  Test1 test1;
  Test2() {}//报错
  Test2(Test1 &t1) { test1 = t1; }//报错
  // Test2(Test1 &t1) : test1(t1) {}
};

int main() {
  Test1 test1;
  Test2 test2(test1);
  }

程序直接就报错了,并且class Test2的无参数构造也报错,为什么呢?
1、类中的成员变量只是声明,真正分配空间在初始化列表中;
2、初始化列表中赋值成员变量等价于调用拷贝构造函数。
3、对于const 引用类型的成员变量一定要在初始化列表中赋值。

最后区别一下 初始化列表和列表初始化
C语言中直接使用{}定义且赋值的操作其实就可以称之为列表初始化

struct Test_ST_A {
    int  num;
    char *ptr;
    float fnum;
};
class Test_Class_A {
public:
    //virtual ~Test_Class_A() {};
    //Test_Class_A() {};
    int  num;
    char *ptr;
    float fnum;
private:
    //Test_Class_A(const Test_Class_A &) {};
};

int main() {
    Test_ST_A st_a = { 0, NULL, 1.1};

    Test_Class_A cla_a = { 0, NULL, 1.1};
    return 0;
}

在C++中是可以直接使用{}包含多个参数直接对内部数据进行初始化的,并且这些参数的类型是可以不一致的;同时如果定义了构造函数、虚函数之类的则无法再这样初始化了,必须定义符合一致的Test_Class_A(int, const char* , float) {};构造函数方可。这就是列表初始化,调用的是构造函数哟

initializer_list
这个类主要是针对于容器来的,对于容器来说也应当想C语言中数组一样提供类似的初始化、赋值函数

int main() {
    std::vector v = {1, 2, 3};
    return 0;
}

这里可以当作简单的语法糖,但是当我们期望传入一个{}()来初始化一个类内部的vector该如何呢?

class Test_Class_A {
public:
    //virtual ~Test_Class_A() {};
    Test_Class_A(std::initializer_list l): data(l) {
        
    };
    std::vector data;
};

int main() {
    Test_Class_A tca = { 1, 2, 3};
    return 0;
}

如果一个类我们如下:

class Test1 {
public:
  //  Test1() // 无参构造函数
  //  {
  //    std::cout << "Construct Test1" << std::endl;
  //  }
  Test1(const Test1 &t1) // 拷贝构造函数
  {
    std::cout << "Copy constructor for Test1" << std::endl;
    this->a = t1.a;
  }
  Test1 &operator=(const Test1 &t1) // 赋值运算符
  {
    std::cout << "assignment for Test1" << std::endl;
    this->a = t1.a;
    return *this;
  }
  int a;
};

我们把无参数构造注释掉,我们在测试类中定义:

class Test2 {
public:
  Test1 test1{};
  }

编译的时候就会发现报错,为什么呢,这是因为在初始化列表中调用了无参数构造,但是Test1却没有无参数构造,所以报错。
也就是说,在类成员变量中加出列化列表这是告诉编译器,这些参数我要在调用默认初始化列表中调用这些参数的构造函数。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/665602.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号