c++中如何处理对象的创建与销毁的时机?
对象创建时机
栈上对象
在函数内部定义的非静态局部对象,当程序执行流到达该对象定义语句时创建。例如:
void func() {
int a; // 基本数据类型对象(这里视为简单的对象示例),此时a被创建
MyClass obj; // MyClass类型的对象obj在这一行被创建
// 函数体其他部分
}
这些对象的生命周期与所在的函数块相关。当函数执行结束,对象就会被销毁。
堆上对象
通过new操作符创建的对象在堆上分配内存。例如:MyClass* ptr = new MyClass();。
这种对象创建的时机是在执行new操作的时候。通常,在需要动态分配内存,并且对象的生命周期需要由程序员手动控制时使用。例如,当对象的生命周期需要跨越多个函数调用或者其生存时间不确定时。
静态对象
静态局部对象:在函数内部定义的静态局部对象,在第一次执行到该对象定义语句时创建,并且只会创建一次。例如:
void func() {
static MyClass staticObj; // 第一次调用func时创建,之后再调用func时不会重新创建
// 函数体其他部分
}
全局静态对象和命名空间作用域内的静态对象在程序启动时创建。它们的生命周期贯穿整个程序的运行时间。
成员对象
当包含它的类对象被创建时,成员对象也会被创建。例如:
class Container {
public:
MemberClass member;
Container() {}
};
int main() {
Container c; // 创建Container对象c时,其成员对象member也会被创建
return 0;
}
对象销毁时机
栈上对象
如前面所述,栈上对象在其所在的函数块结束时自动销毁。编译器会在函数返回之前插入清理栈上对象的代码。这是通过调用对象的析构函数来实现的。例如:
class MyClass {
public:
~MyClass() {
// 析构函数定义,用于清理资源等操作
}
};
void func() {
MyClass obj;
// 函数体其他部分
} // 函数结束时,obj的析构函数被调用,对象被销毁
堆上对象
堆上对象需要通过delete操作符手动销毁。例如,对于前面通过new创建的对象MyClass* ptr = new MyClass();,需要使用delete ptr;来销毁对象。如果忘记删除堆上对象,会导致内存泄漏。
当使用智能指针(如std::unique_ptr、std::shared_ptr)时,对象的销毁时机由智能指针自动管理。例如,std::unique_ptr<MyClass> ptr = std::make_unique<MyClass>();,当ptr离开其作用域时,它所管理的对象会自动被销毁。
静态对象
静态局部对象在程序结束时销毁,或者在包含它的动态链接库(DLL)被卸载时销毁(如果是在 DLL 中定义的静态局部对象)。
全局静态对象和命名空间作用域内的静态对象在程序结束时销毁。它们的析构函数会在main函数结束后的静态对象析构阶段被调用。
成员对象
当包含它的类对象被销毁时,成员对象的析构函数会被调用,从而销毁成员对象。析构函数的调用顺序与构造函数相反。例如,在前面的Container类中,如果Container对象c被销毁,其成员对象member的析构函数会在Container的析构函数中被调用,以确保正确地清理成员对象所占用的资源。