C++构造函数理解

C++ Constructor Understanding

本文关键字:构造函数 C++      更新时间:2023-10-16

考虑这个构造函数:Packet() : bits_(0), datalen_(0), next_(0) {}

注意,bits_datalen_next_是分组类中的字段,定义如下:

u_char* bits_;
u_int datalen_;
Packet* next_;

构造函数的这一部分是什么意思?bits_(0), datalen_(0), next_(0)

这是一个初始值设定项列表,它将值设置为指定的值。

Packet() : bits_(0), datalen_(0), next_(0)
{
    assert( bits_ == 0 );
    assert( datalen_ == 0);
    assert( next_ == 0);
}
//...
Packet()
{
    //bits_ , datalen_, next_ uninitialized here
}

某些成员(const成员或没有默认构造函数的用户定义类成员)无法在初始值设定项列表之外进行初始化:

class A
{
    const int x;
    A() { x = 0; }  //illegal
};
class A
{
    const int x;
    A() : x(0) { }  //legal
};

还值得一提的是,使用这种技术不会发生双重初始化:

class B
{
public:
   B() { cout << "default "; }
   B(int) { cout << "b"; }
};
class A
{
   B b;
   A() { b = B(1); }   // b is initialized twice - output "default b"
   A() : b(1) { }      // b initialized only once - output "b"
}; 

这是初始化成员的首选方式。

这意味着首先bits_,然后datalen_和最后next_

Packet()
     : bits_(0)
     , datalen_0)
     , next_(0)
{
}

这个:

Packet()
{
    bits_ = 0;
    datalen_ = 0;
    next_ = 0;
}

不过要小心。初始化顺序由成员声明顺序决定。也就是说,以下代码无法按预期工作:

struct Packet
{
    int first;
    int second;
    Packet()
        : second(0)
        , first(second)
    {
    }
};

它将相当于:

struct Packet
{
    int first;
    int second;
    Packet()
    {
        first = second;
    second = 0;
    }
};

因此第二个将收到一个0,但第一个

它被称为初始化器列表,它用括号中指定的值初始化字段。以下将实现相同的最终效果:

Packet()
{
    bits_ = nullptr;  // or 0 or NULL pre-C++11
    datalen_ = 0;
    next_ = nullptr;
}

不同的是,在我的例子中,你正在进行赋值,字段已经由它们的默认构造函数构造了。

对于没有默认构造函数的用户定义类型,初始值设定项列表是唯一的方法,因为您需要向构造函数提供一些参数。