构造函数初始化列表

构造函数初始化列表,就是那个冒号的写法

这种方法是为了写起来方便的,也没有特别的含义

用法

1
2
3
4
5
6
class A
{
int a, b,c;
public:
A(int ax, int bx, int cx):a(ax),b(bx),c(cx){}
}

仅仅是为了简洁,就相当于下面

1
2
3
4
5
6
A(int ax, int bx, int cx)
{
a = ax;
b = bx;
c = cx;
}

但是有几点值得注意的

  • 可以在冒号后面写一部分,在函数体写一部分

  • 赋值的顺序是按照类声明中的顺序出现的,而不是书写的顺序

    比如上面的例子如果构造函数这么写

    1
    2
    A(int ax, int bx, int cx):c(cx),a(ax),b(bx)
    {}

    其结果仍然是a,b,c的赋值顺序,而不是按照c,a,b的顺序

    但是这个是在执行函数体之前执行的,所以部分在函数体内部赋值的不受影响

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include <iostream>
    class A
    {
    int a, b, c;
    public:
    A(int ax, int bx, int cx) :c(cx), b(c)
    {
    a = ax;
    }

    void Print()
    {
    std::cout << a << " " << b << " " << c << std::endl;
    }
    };

    int main()
    {
    A d(1, 2, 3);
    d.Print();
    }

    运行的结果是

    1
    1 -858993460 3

    可看执行的顺序大概是

    1
    2
    3
    b = c;
    c = cx;
    a = ax;
  • 对于const,只能用这种方式赋值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #include <iostream>
    class A
    {
    const int len;
    int* a;
    public:
    A(int l):len(l)
    {
    a = new int[len];
    }

    };

    int main()
    {
    A b(1);
    std::cin.get();
    }
  • 最开始提到的两种等效关系,其实实现方式是有区别的,在下面的这个例子中会体现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    class A
    {
    public:
    A()
    {
    std::cout<<"Create"<<std::endl;
    }
    A(int x)
    {
    std::cout<<"Create with" << x<< std::endl;
    }
    };

    class B
    {
    private:
    int x, y;
    A m_a;
    public:
    B(int a)
    {
    m_a = A(a);
    }
    };

    在上面的例子中,使用

    1
    A e(8);

    会输出

    1
    2
    Create
    Create with 8

    这里B被创造了两次?why?

    因为在实例化的时候就使用A m_a,调用了一次构造函数

    然后在赋值的时候又调用了一次构造函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    class A
    {
    public:
    A()
    {
    std::cout<<"Create"<<std::endl;
    }
    A(int x)
    {
    std::cout<<"Create with" << x<< std::endl;
    }
    };

    class B
    {
    private:
    int x, y;
    A m_a;
    public:
    B(int a) :m_a(A(a)){} //或者写成 m_a(a)
    };

    这样就不会调用两次构造函数,因为创造实例的时候调用一次构造函数之后就没有调用了

参考博文:C++构造函数初始化列表

  • © 2019-2022 Wendell
  • Powered by Hexo Theme Ayer

请我喝杯咖啡吧~

支付宝
微信