Inside the C++ Model第二讲之 成员初始化列表(Member Initialization List)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010772289/article/details/75808042

对于C++的成员初始化列表(member initialization list),在以下情况下必须使用
1 当初始化一个reference member时
2 当初始化一个const member时
3 当调用一个base class的构造函数,而它拥有一组参数时
4 当调用一个member class的constructor,而它拥有一组参数时。
例如:

class Word {
    String _name;
    int _cnt;
  public:
// not wrong, just naive ...
    Word() {
        _name = 0;
    _cnt = 0;
    }
};

这里,Word的构造函数首先会产生一个临时的String对象,然后将它初始化,之后以一个assignment运算符将临时的对象指定给_name,然后再销毁那么临时性对象.这样效率不高.
一个更有效率的写法:

// preferred implementation
Word::Word : _name( 0 )
{
    _cnt = 0;
}

This expands to something like this:

// Pseudo C++ Code
Word::Word( /* this pointer goes here */ )
{
    // invoke String( int ) constructor
    _name.String::String( 0 );
    _cnt = 0;
}

Member initialization list中的初始化顺序是由class中的members声明顺序决定的,不是由initialization list中的排列顺序决定的.在这个Word class中,name被声明于_cnt之前,所以它的初始化比较早.另外,initialization list中的项目被放在explicit user code之前.在下面这个例子中,这个是合法的,虽然成员变量i在j之前声明,但是初始化时,initialization list操作在explicit user code之前,也就是说j的初始化操作被安插在i=j之前,因此,i=j是合法的.

class X {
    int i;
    int j;
  public:
    // oops! do you see the problem?
    X( int val ): j( val ), i( j ){}
    ...
};

X::X( int val ): j( val )
{
    i = j;
}

再补充<剑指offer>中的一个例子:

class A
{
  private:
    int n1;
    int n2;
  public:
    A(): n2(0), n1(n2+2) {}
    void Print() { cout<<n1<<”,”<<n2; }
};
int main()
{
    A a;
    a.print();
    return 0;
} 

输出是什么?答案是n1是随机值,因为成员变量中n1的声明顺序在n2之前,因此n1先被初始化,由于此时n2还没初始化,因此它的值是随机的,那么此时用n2加2去初始化n1,n1的值也是一个随机值.

在成员初始化列表中初始化类成员,可以提高速度,因为免去了调用一次拷贝构造函数和赋值构造函数的开销,也没有临时对象的产生。
编译器对初始化列表的处理:会一一操作列表的内容,以适当顺序在constructor之内安插初始化操作,并且在任何explicit user code之前。并且这些构造函数的初始化顺序是根据类中成员声明顺序决定的,不是初始化列表中的顺序。

猜你喜欢

转载自blog.csdn.net/u010772289/article/details/75808042