当前位置:   article > 正文

C++基础——初始化列表_c++初始化列表

c++初始化列表

目录

一.初始化列表

1.列表格式:

情况1: 成员变量中有const成员—— 但列表处成员不被初始化时

情况1: 成员变量中有const成员—— 给缺省值时:

 情况1: 成员变量中有const成员—— 列表处成员不仅初始化,还有缺省值

情况2:成员是自定义类型成员时:

优化方案1:使得类A有默认构造

 优化方案2:采用初始化列表

总结:


一.初始化列表


        虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化,构造函数体中的语句只能将其称为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值。采用从初始化列表的缘故是因为成员变量中会存在一些特殊情况,只能由初始化列表去赋值。

1.列表格式:

        以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟
一个放在括号中的初始值或表达式。
 

自定义类型 类型名(    )   

        :  成员变量1 (赋值)

        ,  成员变量2 (赋值)

        ,  成员变量3 (赋值)

        ......

        {

        //构造函数内部......

        }

【注意】:

1. 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)

例,代码如下:

  1. class Date
  2. {
  3. public:
  4. //构造函数
  5. Date(int year, int month, int day)
  6. //初始化列表
  7. :_year(1999)
  8. ,_month(10)
  9. ,_day(30)
  10. {
  11. _year = year;
  12. _month = month;
  13. _day = day;
  14. }
  15. void Print()
  16. {
  17. cout << "Print()" << endl;
  18. cout << "year:" << _year << endl;
  19. cout << "month:" << _month << endl;
  20. cout << "day:" << _day << endl << endl;
  21. }
  22. private:
  23. int _year; // 年
  24. int _month; // 月
  25. int _day; // 日
  26. };
  27. int main(){
  28. Date d1;
  29. }

        当创建对象d1时,调用该类构造函数,在进入构造函数前,各成员变量都是随机值,编译器会先进入初始化列表,为各成员变量初始化值。

例2:Stack类初始化列表:

  1. typedef int DataType;
  2. class Stack
  3. {
  4. public:
  5. Stack(size_t capa)
  6. //初始化列表
  7. :_size(0)
  8. , _capacity(capa)
  9. , _array((DataType*)malloc(capa * sizeof(DataType)))
  10. {
  11. //构造函数内部
  12. if (nullptr == _array)
  13. {
  14. perror("malloc申请空间失败");
  15. return;
  16. }
  17. }
  18. void Push(const DataType& data)
  19. {
  20. // CheckCapacity();
  21. _array[_size] = data;
  22. _size++;
  23. }
  24. ~Stack()
  25. {
  26. if (_array)
  27. {
  28. free(_array);
  29. _array = nullptr;
  30. _capacity = 0;
  31. _size = 0;
  32. }
  33. }
  34. private:
  35. DataType* _array;
  36. size_t _size;
  37. size_t _capacity;
  38. };

        也可以将构造函数和初始化列表混合着用:

  1. typedef int DataType;
  2. class Stack
  3. {
  4. public:
  5. Stack(size_t capa)
  6. :_size(0)
  7. , _capacity(capa)
  8. {
  9. //构造函数内部
  10. _array =(DataType*)malloc(capa * sizeof(DataType));
  11. if (nullptr == _array)
  12. {
  13. perror("malloc申请空间失败");
  14. return;
  15. }
  16. }

        在初始化列表中先初始化size和capacity,针对于指针开辟空间的成员还是放在构造函数内部好,因为要与判断相连接,还是混着来比较好。

初始化列表最重要的作用就是为特殊的成员变量提供初始化帮助: 

 2. 类中包含以下成员,必须放在初始化列表位置进行初始化:

        引用成员变量

        const成员变量

        自定义类型成员(且该类没有默认构造函数时) 

        当我们在定义const变量时,往往需要定义时就要给初始化值:

         而构造函数并不能满足需求,需要用到初始化列表。

情况1: 成员变量中有const成员—— 但列表处成员不被初始化时

  1. class B{
  2. public:
  3. B()
  4. :_n(10) //初始化列表
  5. {}
  6. private:
  7. const int _n; // const
  8. int _m;
  9. };

 

        总结:每个成员都要走初始化列表,就是成员没有在初始化列表写,也会走。但初始化列表只有_n被初始化,而_m没有,所以赋给随机值 

情况1: 成员变量中有const成员—— 给缺省值时:

  1. class B
  2. {
  3. public:
  4. B()
  5. :_n(10) //初始化列表
  6. {}
  7. private:
  8. const int _n; // const
  9. int _m=1; //缺省值
  10. };
  11. int main() {
  12. B b2;
  13. }

        总结:因为成员变量处给了缺省值,但此时_m还处于随机值,直到运行时编译器进入构造函数初始化列表,_m才会使用缺省值 

 情况1: 成员变量中有const成员—— 列表处成员不仅初始化,还有缺省值

  1. class B
  2. {
  3. public:
  4. B(int a, int ref)
  5. :_n(10) //初始化列表
  6. , _m(3)
  7. {}
  8. private:
  9. const int _n; // const
  10. int _m=100; //缺省值
  11. };

        总结:这次,_m不仅有缺省值,还在初始化列表中被初始化,而编译器会优先选择初始化列表的值初始化列表使用权>缺省值使用权限,所以最终_m最终是按照初始化列表的赋值使用,其值为3。


情况2:成员是自定义类型成员时:

  1. class A{
  2. public:
  3. //构造函数,并不是默认构造
  4. A(int a)
  5. :_a(a)
  6. {}
  7. private:
  8. int _a;
  9. };
  10. class B{
  11. public:
  12. B()
  13. :_n(10) //初始化列表
  14. {}
  15. private:
  16. const int _n; // const
  17. A _aa;
  18. };
  19. int main() {
  20. B b4;
  21. }

       总结:编译器执行对象b4的创建时,会进入类B的构造函数,因为成员变量有自定义类型 _aa,所以编译器会进入类A中找它的默认构造,但类A中没有默认构造,类A中只有自己写的构造函数,此时也就无法给自定义类型成员_aa赋值,所以编译器会报错。  

优化方案1:使得类A有默认构造函数(这个默认构造可以是全缺省的构造函数,也可以是无参构造,或者直接不写由编译器自动生成的构造函数)

        编译器运行正常,自定义类型成员变量_aa赋值为10,const成员变量_n初始化值为10。

 优化方案2:让类A放弃默认构造,采用初始化列表

  1. class A{
  2. public:
  3. //不采用默认构造,但初始化列表给值了也不会报错
  4. A(int a )
  5. :_a(a)
  6. {}
  7. private:
  8. int _a;
  9. };
  10. class B{
  11. public:
  12. B()
  13. :_n(10) //初始化列表
  14. ,_aa(75)
  15. {}
  16. private:
  17. const int _n; // const
  18. A _aa;
  19. };
  20. int main() {
  21. B b;
  22. return 0;
  23. }

        调用b的成员时,即调用A _aa时会到A类中调用它的默认构造,没有默认构造时,使用初始化列表,也不会报错。 

        对于引用成员来说,它与const一样,都是需要在定义时就得初始化,而采用构造函数并不能满足需求,只能使用初始化列表。


总结:

      1. 对于内置类型,没有成员在初始化列表中显示时,有缺省值就使用缺省值,没有缺省值就只能是随机值。
       2.对于自定义类型,调用它的默认构造函数,若没有默认构造函数,则报错!!!
       3.默认构造三种形式:无参构造、全缺省构造、不亲自写编译器自己生成的默认构造。

       4.要尽量使用初始化列表去初始化成员变量(因为有const、自定义类型、引用)。

       5.尽量提供默认构造函数(推荐:全缺省)。

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/209062
推荐阅读
相关标签
  

闽ICP备14008679号