C++ 类中变量可以通过以下方式进行初始化:
- 构造函数初始化列表:在类的构造函数中使用初始化列表来初始化成员变量,这是最常用的初始化方式。
例如:
class MyClass {
public:
MyClass(int a, int b) : x(a), y(b) {}
private:
int x;
int y;
};
- 默认构造函数:如果类没有定义任何构造函数,则编译器会自动生成一个默认构造函数,在默认构造函数中会初始化成员变量。
例如:
class MyClass {
public:
MyClass() {}
private:
int x = 0;
int y = 0;
};
- 类内初始化:在类定义中直接初始化成员变量。
例如:
class MyClass {
public:
MyClass() {}
private:
int x = 0;
int y = 0;
};
- 静态成员变量初始化:静态成员变量可以在类外进行初始化。
例如:
class MyClass {
public:
MyClass() {}
private:
static int x;
static int y;
};
int MyClass::x = 0;
int MyClass::y = 0;
5.构造函数体内赋值
class MyClass {
public:
MyClass(int a, int b) {
x = a;
y = b;
}
private:
int x;
int y;
};
构造函数初始化列表 和 构造函数体内赋值 的比较
成员初始化列表会在构造函数体之前,先对成员变量进行初始化。而构造函数体内赋值是在构造函数体内进行的。
相比之下,成员初始化列表的效率更高,因为它可以在编译时进行优化,避免了先构造再赋值的操作。而构造函数体内赋值则需要先构造成员变量,再对它们进行赋值,因此效率相对较低。
此外,构造函数体内赋值还存在一个潜在的问题:如果成员变量是const或者引用类型,则必须通过成员初始化列表进行初始化,因为它们无法在构造函数体内被赋值。如果使用构造函数体内赋值,则会导致编译错误。
同时构造函数体内赋值还存在多线程竞态问题
如果一个对象被多个线程同时使用,那么在第二种初始化方式中,如果一个线程正在对成员变量进行赋值,而另一个线程同时也访问了这些成员变量,就会发生竞态条件(Race Condition)。
竞态条件是指多个线程同时访问并修改共享的数据,导致数据的最终结果不确定,可能会出现预期之外的结果或者崩溃。
在第二种初始化方式中,由于成员变量是在构造函数体内赋值,而构造函数的执行是不可分割的,因此在同一时间只有一个线程可以执行构造函数,因此不存在多线程竞态的问题。但是如果对象在构造完成之后被多个线程同时访问,那么就会存在多线程竞态的问题,因为多个线程可以同时访问和修改这些成员变量。
相比之下,使用成员初始化列表的方式可以避免多线程竞态问题,因为成员初始化列表可以在构造函数之前对成员变量进行初始化,而不需要等待构造函数体执行完成。因此,建议在多线程环境下使用成员初始化列表来初始化成员变量。