【问题标题】:Do I have to explicitly destroy objects in order我是否必须按顺序明确销毁对象
【发布时间】:2017-05-12 00:05:41
【问题描述】:

我知道,当为您提供隐式构造函数时,您的类成员会从左到右和从上到下进行初始化。换句话说,按照它们被声明的顺序。然后,当类对象超出范围时,所有成员都以相反的顺序被破坏。但是,如果我必须自己销毁成员,我是否必须按照它们列出的确切顺序进行操作?例如:

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?

};

谢谢。

【问题讨论】:

    标签: c++ class struct destructor


    【解决方案1】:

    请记住,删除指针指向的对象和销毁指针本身是有区别的。当包含对象的生命周期结束时,C++ 会自动销毁指针本身,并且会按照与构造它们的顺序相反的顺序进行销毁。您可以按照自己喜欢的任何顺序随意删除这些指针,具体取决于对象的设置方式。

    请注意,如果您从使用原始指针更改为 unique_ptrs,那么这将完全为您处理,甚至根本不需要析构函数!

    【讨论】:

      【解决方案2】:

      但如果我必须自己销毁成员,我必须按照它们列出的确切顺序执行吗?

      不,按你喜欢的顺序做。

      但我更喜欢匹配“自动”顺序,以免感到惊讶。

      我认为提供的析构函数是一个空的。因此,当我听说该类在超出范围时会调用其成员的析构函数时,它不会在自己的析构函数中执行此操作,而是在其之后使用编译器单独生成的代码?

      基本上是的。

      析构函数体的执行是析构的一部分。另一部分是摧毁所有成员和基地。

      【讨论】:

      • 我明白了。我开始认为反向销毁只对堆栈上的东西重要,而不是堆?我错了吗?编辑:不用等待,但是可以在堆上创建类对象。哦,我很困惑。
      • @TitoneMaurice:取决于你所说的“重要”是什么意思。
      • @TitoneMaurice - 这总是很重要的,特别是如果成员是相互关联的对象。您不想以错误的顺序销毁它们。
      • @StoryTeller:如果他们彼此不相关,那么这根本不重要。
      • 这种语言让我很难学。无法形容的数字或规则和例外。我经常看到甚至 20 年的老手说“我以前从未见过这种情况”,比如在 try catch 中包围构造函数
      【解决方案3】:

      您在析构函数中销毁对象的顺序通常无关紧要,除非出于某种原因,它应该基于对象拥有的资源需求。

      例如,如果您要删除拥有的线程对象,您可能希望在删除线程可能使用的项目之前确保线程已退出。 shared_ptr 和其他智能指针在这些情况下很有帮助。它们还有助于减少对析构函数的需求。

      【讨论】:

        【解决方案4】:

        正如轨道中的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
        };
        

        析构函数将执行它的主体,然后,它将开始以相反的顺序删除它的剩余成员。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-12-23
          • 2015-09-06
          • 2011-04-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多