成员初始化列表的使用及特点

成员初始化列表:用于辅佐构造函数(可以是默认构造函数),对成员变量进行赋值。

一般情况下,使用成员初始化列表与在构造函数内部对成员进行赋值没有什么好坏之分,使用哪种方式对对象进行初始化全凭心情。

但是,在以下四种情况的成员变量中,只能使用成员初始化列表进行初始化:

1.当初始化一个const member时。这种情况不用多说,对于const变量的初始化只能使用初始化列表,而不能在constructor中进行赋值,不然违背成员变量const的性质。

2.当初始化一个reference member时。平常对于引用的研究比较少,等看完手头的书专门看下引用。这里因为成员变量的属性为引用类型,代表这个成员变量将是另一个变量的别名,他们不仅仅是值相等,其实更是互相等价。因为在使用的时候,必须要先初始化在赋值,也就是说,必须要int& c=a;后才可以c=100;而如果不在成员初始化列表中先初始化,是不可以在constructor中直接赋值的。

3.调用一个base class的constructor,而它拥有一组参数时。

4.调用一个member class的constructor,而它拥有一组参数时。

3与4其实是很相近的,它们都是因为需要使用的调用的constructor中本来就需要用成员初始化列表进行初始化。

讲完了使用,下面看下成员初始化列表的特点

首先是当使用了成员初始化列表后,整个构造函数的运行顺序:

实际上,编译器会对成员初始化列表进行操作,将它们安插在constructor之中,但这是有一个先后顺序的:

一定是优先进行成员初始化列表中的操作,然后在进行原本设计在constructor中的操作。

其次,在成员初始化列表的操作中,一定是按照声明先后顺序进行初始化!

在以下情况:

class A

{

  int a;

  int b;

  A(int val):b(val),a(b)

  {

  }

}

看似好像是先用val初始化b,然后用b初始化a。但实际上,按照声明的先后顺序,应该优先进行的是a(b),而此时b是个不知道为多少的鬼值,因此a也被初始化为一个鬼,在进行b=val。

因此,在成员初始化列表中初始化时,当出现用类中成员去初始化另一个成员时,一定要注意声明先后顺序。而在constructor中进行初始化则不用考虑这些,因为constructor中一定是按照你赋值语句的顺序进行的。

另外,在设计到基类成员时,也会涉及到先后顺序的问题:

class FooBar:public X{

  int _fval;

public:

  int fval(){return _fval;}

  FooBar(int val):_fval(val),X(fval())

  {}

}

从语意上来说,好像是想用val初始化派生类的成员_fval,在用派生类成员_fval去初始化基类的成员。

然而,在内存布局上,基类的成员是先于派生类声明的,因此实际上达到的效果为:

FooBar::FooBar(this,int val)

{

  X::X(this,this->fval);

  _fval=val;

}

这个顺序恰好与所想的相反,基类被初始化为一堆不知道是多少的数后才开始初始化派生类的_fval成员。

原文地址:https://www.cnblogs.com/lxy-xf/p/11049863.html

时间: 2024-08-03 01:03:32

成员初始化列表的使用及特点的相关文章

【C/C++】构造函数、默认构造函数、成员初始化列表

常见问题 Q1. 下列关于构造函数的描述中,错误的是( ) A. 构造函数可以设置默认的参数 B. 构造函数在定义类对象时自动执行 C. 构造函数可以是内联函数 D. 构造函数不可以重载 Q2. 下列代码中a.b的各个成员变量值是多少? 1 class Student 2 { 3 public: 4 Student() {} 5 void show(); 6 private: 7 string name; 8 int number; 9 int score; 10 }; 11 Student a

C++对象模型——成员初始化列表(第二章)

2.4    成员初始化列表 (Member Initialization List) 当编写一个类的构造函数时,有可能设定类成员的初始值,或者通过成员初始化列表初始化,或者在构造函数内初始化,除了四种情况,其实任何选择都差不多. 本节中,首先澄清何时使用初始化列表才有意义,然后解释初始化列表内部的真正操作是什么,然后再看一些微妙的陷阱.  下列情况中,为了让程序能够被顺利编译,必须使用成员初始化列表(不能在构造函数内初始化): 1.    当初始化一个引用的成员时 2.    当初始化一个常量

c++类 用冒号初始化对象(成员初始化列表)

c++类 用冒号初始化对象(成员初始化列表) 成员初始化的顺序不同于它们在构造函数初始化列表中的顺序,而与它们在类定义中的顺序相同 #include<iostream> int n=0; using namespace std; class Cbox{ int a ; int b ; int c ; public: int g ; Cbox():a(n++),c(n++),b(n++){} ~Cbox(){cout<<a<<" "<<b&

C++:用成员初始化列表对数据成员初始化

1.在声明类时,对数据成员的初始化工作一般在构造函数中用赋值语句进行. 例如: class Complex{ private: double real; double imag; public: Complex(double r,double i) //声明构造函数原型 { ........... } }; Complex::Complex(double r,double i) //在构造函数中用赋值语句对数据成员赋初值 { real = r; imag = i; } 2.另一种初始化数据成员的

C++类的成员初始化列表的相关问题

在以下四中情况下,要想让程序顺利编译,必须使用成员初始化列表(member initialization list): 1,初始化一个引用成员(reference member): 2,初始化一个常量对象(const member); 3,调用一个基类的构造函数,且该基类的构造函数有一组参数: 4,调用一个成员类(member class)的构造函数,且该构造函数有一组参数 这四种情况程序可以正常编译,但是效率有所欠缺(下面会具体说到). class Word{ String _name; in

C++成员初始化列表

class A { public: A() { cout << "class A default constructor called" << endl; a = 0; } A(int param) { cout << "class A constructor called" << endl; a = param; } ~A() { } virtual void FunctionA() { cout <<

C++类成员初始化列表的构造顺序

看下面代码, 输出结果是多少呢? class A{ public: A(int k) : j(k), i(j) { } void show() { cout << this->i << endl; cout << this->j << endl; } private: int i; int j; }; void test() { A a(3); a.show(); } int main(int argc, char const *argv[])

条款十三: 初始化列表中成员列出的顺序和它们在类中声明的顺序相同

template<class t> class array { public: array(int lowbound, int highbound); ... private: vector<t> data; // 数组数据存储在vector对象中 // 关于vector模板参见条款49 size_t size; // 数组中元素的数量 int lbound, hbound; // 下限,上限 }; template<class t> array<t>::a

初始化列表的用法说明

类对象的构造顺序是这样的:1.分配内存,调用构造函数时,隐式/显示的初始化各数据成员2.进入构造函数后在构造函数中执行一般计算 使用初始化列表有两个原因: 1.必须这样做:   <C++ Primer>中提到在以下三种情况下需要使用初始化成员列表: 一.需要初始化的数据成员是对象的情况:二.需要初始化const修饰的类成员:三.需要初始化引用成员数据:        如果我们有一个类成员,它本身是一个类或者是一个结构,而且这个成员它只有一个带参数的构造函数,而没有默认构造函数,这时要对这个类成