我知道当为您提供隐式构造函数时,您的类成员将从左到右,从上到下进行初始化。换句话说,按照他们宣布的顺序。然后当类对象超出范围时,所有成员都以相反的顺序被破坏。但是,如果我必须自己摧毁成员,我必须按照它们列出的确切顺序进行吗?例如:
struct Dog {};
struct Animal
{
Dog* dog1 = new Dog;
Dog* dog2 = new Dog;
~Animal()
{
delete dog2; // First delete dog2
delete dog1; // Then delete dog1
// Or do I?
}
};
我认为提供的析构函数是空的。因此,当我听到该类在超出范围时会调用其成员的析构函数时,它不会在自己的析构函数中执行此操作,但在此之后,编译器会单独生成代码吗?例如:
struct Animal
{
Dog dog1;
// ~Animal(){}implicitly defined destructor here. dog1 isn't destroyed here
// But is destroyed here, or after, or something along those lines with separate code that the compiler generates?
};
感谢。
答案 0 :(得分:5)
但是,如果我必须自己摧毁成员,我必须按照它们列出的确切顺序进行吗?
不,按照你喜欢的顺序做。
但我更喜欢匹配"自动"为了避免感到惊讶。
我认为提供的析构函数是空的。因此,当我听到该类在超出范围时将调用其成员的析构函数时,它不会在自己的析构函数中执行此操作,但在此之后,编译器会单独生成代码吗?
基本上,是的。
析构函数体的执行是破坏的一部分。另一部分是对所有成员和基地的破坏。
答案 1 :(得分:3)
请记住,删除指针指向的对象和销毁指针本身之间存在区别。当包含对象的生命周期结束时,C ++将自动销毁指针本身,并且它将按照构造它们的顺序反向执行。您可以按照您喜欢的任何顺序自由删除这些指针,具体取决于对象的设置方式。
作为一个注释,如果你从使用原始指针改为unique_ptr
s,那么这将完全为你处理,甚至根本不需要一个析构函数!
答案 2 :(得分:1)
在析构函数中销毁对象的顺序通常无关紧要,除非有某些原因它应该基于对象拥有的资源需求。
例如,如果要删除拥有的线程对象,则可能需要在删除线程可能使用的项之前确保该线程已退出。 shared_ptr和其他智能指针在这些情况下很有用。它们还有助于减少对析构函数的需求。
答案 3 :(得分:1)
正如Orbit中的Lightness Races所回答,你可以按照任何命令摧毁班级成员。但是默认的析构函数(如果没有显式调用)总是遵循特定的顺序来销毁成员,这些成员的顺序与创建的成员的顺序相反。
由于析构函数也是一个函数,您可以在该函数中添加语句,以便在对象的销毁时执行。然后,析构函数将执行这些语句,然后,它将以相反的顺序继续删除类的成员。
例如:
struct Dog {};
struct Animal
{
Dog* dog1 = new Dog;
Dog* dog2 = new Dog;
int var;
~Animal()
{
delete dog1; // First delete dog1
} //delete var and then delete dog2
};
析构函数将执行它的正文,然后它将开始以相反的顺序删除它的剩余成员。