在我的学习机制中,我发现在堆栈展开时会有对象字段的析构函数调用。让我明确解释一下:
class X
{
File_ptr aa;
Lock_ptr bb;
public:
X(const char* x,const char* y):aa(x),bb(y){}
//.......
}
所以,现在如果Lock_ptr的构造函数抛出一个exeption,对象 aa 将被销毁; 问题是"为什么"?我一直认为对象的文件不是通常的自动(lochal)对象。它们是在构造函数初始化它们之前创建的。所以它们在构造函数范围之外不能被破坏(否则它们将是建造者完成工作后立即销毁
答案 0 :(得分:5)
子对象(包括非静态数据成员)与它们所属的完整对象具有相同的存储持续时间。这与说它们是自动的不同。在块结束时销毁自动对象。只要完整对象被销毁,子对象就会被销毁。例如,如果使用new
创建完整对象并使用delete
销毁(即具有动态存储持续时间),则在调用new
时也会创建子对象,并在致delete
的电话。另一方面,自动对象的子对象也是自动的。
如果X::bb
的构造函数抛出异常,则意味着无法构造类型为X
的完整对象。必须销毁已构建的所有子对象,例如X::aa
,因为与完整对象具有相同存储持续时间的子对象在没有完整对象的情况下无法生存。
另一方面,如果整个X
对象的构造成功完成,则X::aa
和其他子对象不会被销毁,直到(不久之后)完整的X
对象被毁了。
C ++的构造和销毁规则旨在保证,只要程序正常终止,所创建的每个对象也只会被销毁一次。这对于RAII成语至关重要。在此示例中,如果X::aa
在构造资源时获取资源,则语言必须确保将释放这些资源。如果X::aa
的构造失败时未调用X
的析构函数,那么何时应该调用它?
答案 1 :(得分:3)
X有一个构造aa
和bb
的“真实”构造函数,然后调用X的构造函数体。这就是初始化列表在X
的构造函数“body”之前的原因。在这个“真正的”构造函数内部,创建base和then成员,好像它们按照它们在类中声明的顺序在堆栈中,包括堆栈展开。我甚至有一张照片:
* QuestionC正确地观察到静态成员完全独立于我在这里写的所有内容。
答案 2 :(得分:0)
成员对象(除非它们是static
)是在调用类构造函数时构造的。您看到的行为是正常和正确的。
构造函数完成后,不会销毁成员对象。调用类析构函数时,它们会被销毁(以相反的构造顺序)。