构造函数调用顺序
- 在C++中,全局对象的构造函数在main函数执行之前被调用。
- 对于不同编译单元(源文件)中的全局对象,其构造顺序是未定义的。但如果全局对象在同一个编译单元中定义,那么它们的构造顺序与定义顺序一致。
- 所以对于类A和类B的全局对象,由于它们在不同源文件中,其构造顺序是未定义的。不过,同一个编译单元内的全局对象构造顺序遵循定义顺序。
优化构造函数调用带来的性能开销
- 减少不必要的初始化:
- 避免在构造函数中进行过多非必要的计算和初始化操作。例如,如果某些数据成员的初始化值在构造后会立即被修改,考虑延迟初始化,即在真正需要时再进行初始化。
- 对于复杂对象的初始化,可以采用成员初始化列表的方式,因为成员初始化列表是按照成员声明的顺序进行初始化的,效率更高。例如:
class Example {
private:
int data1;
int data2;
public:
Example(int a, int b) : data1(a), data2(b) {}
};
- 使用静态局部对象替代全局对象:
- 静态局部对象在第一次使用时才会被构造,这样可以避免在程序启动时就进行不必要的构造。例如:
class MyClass {
public:
MyClass() { /* 构造函数代码 */ }
};
MyClass& getMyClassInstance() {
static MyClass instance;
return instance;
}
- 优化对象构造时的资源分配:
- 如果构造函数涉及到动态内存分配(如使用
new
),考虑使用智能指针来管理内存,这样可以避免内存泄漏,并且在对象析构时自动释放资源。例如:
#include <memory>
class Resource {
public:
Resource() { /* 资源初始化 */ }
~Resource() { /* 资源释放 */ }
};
class Container {
private:
std::unique_ptr<Resource> resourcePtr;
public:
Container() : resourcePtr(std::make_unique<Resource>()) {}
};
- 避免构造函数中的异常:
- 构造函数中抛出异常会导致对象构造不完全,进而可能导致资源泄漏等问题。尽量在构造函数前进行必要的检查,确保构造过程能够顺利完成。如果必须处理异常,可以使用
try - catch
块在构造函数中捕获并处理异常,或者在构造函数外进行检查和处理。