C++对象模型(17)-- 构造函数语义学:成员初始化列表

1、必须用初始化列表的场景

(1)成员变量是引用类型,必须在初始化列表中初始化。

(2)成员变量是const类型,必须在初始化列表中初始化。

(3)如果类继承自一个父类,并且父类中有带初始化列表的构造函数,必须在初始化列表中初始化父类。

class Base {
public:
    Base(int i) { }
};

class Derive:public Base {
public:
    Derive(int i) : Base(i){}
};

(4)成员变量是类类型,且这个类的构造函数带参数。

class Item {
public:
    Item(int i) { }
};

class MyDemo {
public:
    MyDemo(int i) : item(i){}

    Item item;
};

2、初始化列表的执行时机

初始化列表是在构造函数之前执行的。

我们可以用下面的代码来验证:

class Item {
public:
    Item() { }
    Item(const Item& _item) {
        cout << " Item拷贝构造函数" << endl;
    }
};
class Derive {
public:
    Derive() { cout << " Derive默认构造函数" << endl; }
    Derive(Item& _item) : item(_item) { cout << " Derive带初始化列表构造函数" << endl; }

    Item item;
};

int main()
{
    Item _item;
    Derive derive(_item);

    return 0;
}

执行结果如下:

从运行结果看,初始化列表是在构造函数之前运行的。

3、按成员变量的声明顺序初始化,而不是根据初始化列表中的前后顺序。

class X{
public: 
    X(int val) : j(val), i(j){}
private:
    int i;
    int j;
}

其实在这个时候,构造函数是这么初始化的:

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

所以最终的结果是j = val, 但i的值未知。

4、初始化列表的优点

一般地,放在构造函数初始化列表中进行初始化,比放在构造函数中初始化效率更高。

我们可以通过代码来验证这个结论:

(1)构造函数中初始化

class Item {
public:
    Item() { 
        cout << " Item默认构造函数" << endl; 
    }

    Item(int i) { 
        cout << " Item(int)构造函数" << endl; 
    }

    Item(const Item& _item) {
        cout << " Item拷贝构造函数" << endl;
    }

    Item& operator = (const Item& _item) {
        cout << " Item拷贝赋值运算符" << endl;

        return *this;
    }
};

class Derive {
public:
    Derive(int i){ 
        item = Item(i);
        cout << " Derive带初始化列表构造函数" << endl; 
    }

    Item item;
};

int main()
{
    Derive derive(2);

    return 0;
}

运行结果:

(2)初始化列表中初始化

Derive(int i) : item(i){}

运行结果:

可以看到,初始化列表初始化时少了1次默认构造函数和1次拷贝赋值运算符。

你可能感兴趣的:(C++对象模型,c++,对象模型,初始化列表)