转:C++构造函数初始化列表与构造函数中的赋值的区别

转:https://blog.csdn.net/chenlycly/article/details/53558675

C++类中成员变量的初始化有两种方式:

         构造函数初始化列表和构造函数体内赋值。下面看看两种方式有何不同。

         成员变量初始化的顺序是按照在那种定义的顺序。

1、内部数据类型(char,int……指针等)

  1.  
    class Animal
  2.  
    {
  3.  
    public:
  4.  
    Animal(int weight,int height): //A初始化列表
  5.  
    m_weight(weight),
  6.  
    m_height(height)
  7.  
    {
  8.  
    }
  9.  
    Animal(int weight,int height) //B函数体内初始化
  10.  
    {
  11.  
    m_weight = weight;
  12.  
    m_height = height;
  13.  
    }
  14.  
    private:
  15.  
    int m_weight;
  16.  
    int m_height;
  17.  
    };

对于这些内部类型来说,基本上是没有区别的,效率上也不存在多大差异。

当然A和B方式不能共存的。

 

2、无默认构造函数的继承关系中

  1.  
    class Animal
  2.  
    {
  3.  
    public:
  4.  
    Animal(int weight,int height): //没有提供无参的构造函数
  5.  
    m_weight(weight),
  6.  
    m_height(height)
  7.  
    {
  8.  
    }
  9.  
    private:
  10.  
    int m_weight;
  11.  
    int m_height;
  12.  
    };
  13.  
     
  14.  
    class Dog: public Animal
  15.  
    {
  16.  
    public:
  17.  
    Dog(int weight,int height,int type) //error 构造函数 父类Animal无合适构造函数
  18.  
    {
  19.  
    }
  20.  
    private:
  21.  
    int m_type;
  22.  
    };

上面的子类和父类编译会出错:

因为子类Dog初始化之前要进行父类Animal的初始化,但是根据Dog的构造函数,没有给父类传递参数,使用了父类Animal的无参数构造函数。而父类Animal提供了有参数的构造函数,这样编译器就不会给父类Animal提供一个默认的无参数的构造函数了,所以编译时报错,说找不到合适的默认构造函数可用。要么提供一个无参数的构造函数,要么在子类的Dog的初始化列表中给父类Animal传递初始化参数,如下:

 

  1.  
    class Dog: public Animal
  2.  
    {
  3.  
    public:
  4.  
    Dog(int weight,int height,int type):
  5.  
    Animal(weight,height) //必须使用初始化列表增加对父类的初始化
  6.  
    {
  7.  
    ;
  8.  
    }
  9.  
    private:
  10.  
    int m_type;
  11.  
    };
 

3、类中const常量,必须在初始化列表中初始,不能使用赋值的方式初始化

 

  1.  
    class Dog: public Animal
  2.  
    {
  3.  
    public:
  4.  
    Dog(int weight,int height,int type):
  5.  
    Animal(weight,height),
  6.  
    LEGS(4) //必须在初始化列表中初始化
  7.  
    {
  8.  
    //LEGS = 4; //error
  9.  
    }
  10.  
    private:
  11.  
    int m_type;
  12.  
    const int LEGS;
  13.  
    };

 

4、包含有自定义数据类型(类)对象的成员初始化        

 

  1.  
    class Food
  2.  
    {
  3.  
    public:
  4.  
    Food(int type = 10)
  5.  
    {
  6.  
    m_type = 10;
  7.  
    }
  8.  
    Food(Food &other) //拷贝构造函数
  9.  
    {
  10.  
    m_type = other.m_type;
  11.  
    }
  12.  
    Food & operator =(Food &other) //重载赋值=函数
  13.  
    {
  14.  
    m_type = other.m_type;
  15.  
    return *this;
  16.  
    }
  17.  
    private:
  18.  
    int m_type;
  19.  
    };
  20.  
     
  21.  
    1)构造函数赋值方式 初始化成员对象m_food
  22.  
    class Dog: public Animal
  23.  
    {
  24.  
    public:
  25.  
    Dog(Food &food)
  26.  
    //:m_food(food)
  27.  
    {
  28.  
    m_food = food; //初始化 成员对象
  29.  
    }
  30.  
    private:
  31.  
    Food m_food;
  32.  
    };
  33.  
    //使用
  34.  
    Food fd;
  35.  
    Dog dog(fd); //
  36.  
    Dog dog(fd);结果:
  37.  
    先执行了 对象类型构造函数Food(int type = 10)——>
  38.  
    然后在执行 对象类型构造函数Food & operator =(Food &other)
  39.  
    想象是为什么?
  40.  
     
  41.  
    2)构造函数初始化列表方式
  42.  
    class Dog: public Animal
  43.  
    {
  44.  
    public:
  45.  
    Dog(Food &food)
  46.  
    :m_food(food) //初始化 成员对象
  47.  
    {
  48.  
    //m_food = food;
  49.  
    }
  50.  
    private:
  51.  
    Food m_food;
  52.  
    };
  53.  
    //使用
  54.  
    Food fd;
  55.  
    Dog dog(fd); //
  56.  
    Dog dog(fd);结果:执行Food(Food &other)拷贝构造函数完成初始化

 

不同的初始化方式得到不同的结果:

      明显构造函数初始化列表的方式得到更高的效率。

posted @ 2018-07-16 23:13  撑伞的猫先生。  阅读(90)  评论(0编辑  收藏  举报