类成员初始化顺序

 
 
class A
{
public:
    A(int n){
        cout << "A ..." << endl;
    }
    ~A(){}
};

class B
{
public:
    B(int n){
        cout << "B ..." << endl;
    }
    ~B(){}
};

class MyClass
{
public:
    MyClass();
    ~MyClass(){}

private:
    B m_b;
    A m_a;
    int m;
    string m_str;
    int n;
};

MyClass::MyClass():m_a(1),m_b(2)
{
    n = 100;
    m = 99;
    m_str = "138182";
    cout << "MyClass ..." << endl;
}

说明:成员被初始化的顺序,与初始化列表里面的顺序没有关系,只和成员的声明顺序有关。先声明的,先初始化。

class A
{
public:
    A(){
        cout << "A ...000" << endl;
    }
    A(int n){
        cout << "A ...111" << endl;
    }
//    A(A& a){}
    ~A(){}
};

class B
{
public:
    B(){
        cout << "B ...000" << endl;
    }
    B(int n){
        cout << "B ...111" << endl;
    }
//    B(B& b){}
    ~B(){}
};

class MyClass
{
public:
    MyClass();
    ~MyClass(){}

private:
    B m_b;
    A m_a;
    int m;
    string m_str;
};

MyClass::MyClass()
{
    cout << "MyClass ..." << endl;
    m = 99;
    m_str = "138182";
    m_a = 1;
    m_b = 2;
}

1.内置数据类型,复合类型(指针,引用)
    在成员初始化列表中初始化,和在构造函数体内赋值,性能和结果完全一样。
2.用户定义类型(类类型)
    
结果上相同,但是性能上存在很大的差别。因为类类型的数据成员对象在进入函数体前已经构造完成,也就是说在成员初始化列表处进行构造对象的工作,调用构造函数,在进入函数体之后,进行的是对已经构造好的类对象的赋值,又调用个拷贝赋值操作符才能完成(如果并未提供,则使用编译器提供的默认按成员赋值行为)

总结:

1、初始化列表中的初始化顺序,至于类成员的声明顺序有关,直接调用构造函数进行初始化;

2、在类的构造函数中对类成员进行赋值,这些成员对象在进入函数体之前要先完成构造,必须得有合适的构造函数可用(无参数的构造函数,或有默认参数的构造函数);

进入函数体之后,再对已经构造好的类对象进行赋值,要调用构造函数,再调用赋值运算符(有默认赋值运算符)

猜你喜欢

转载自www.cnblogs.com/pjl1119/p/9653158.html
今日推荐