基于异常展开发生了跟随破坏吗?

时间:2014-03-03 01:01:50

标签: c++ exception constructor

Class Object {
public:
    Object() {
        this->objectMember=ObjectMember(10); 
        this->pobjectMember=new ObjectMember(20);
        throw 1;
    }

    ~Object():objectMember(10) {
        this->pobjectMember=new ObjectMember(20);
        throw 1;
    }

private:
    ObjectMember objectMember ;
    ObjectMember *pobjectMember ;
}

当调用Object *o = new Object()时,它会抛出异常。

Q1:成员:objectMember将被破坏。它是由异常展开还是其他机制引起的?

Q2:成员pobjectMember也会被破坏吗?有人提到pobjectMember会被解构但是没有任何东西可以用于指针的破坏过程吗?这样对吗?

问题3:通过调用delete auto?

来释放为新Object分配的内存

任何官方文章都讨论过这个问题?

3 个答案:

答案 0 :(得分:0)

  

Q1:成员:objectMember将被破坏。它是由异常展开还是其他机制引起的?

截至§15.2/ 3:

  

为从try块到抛出异常的路径构造的自动对象调用析构函数的过程称为“堆栈展开”。如果在堆栈展开期间调用的析构函数以异常退出,则std :: terminate被称为(15.5.1)。 [注意:因此析构函数通常应该捕获异常,而不是让它们从析构函数中传播出来。

所以,是的,这就是它的召唤方式。


  

Q2:成员pobjectMember也会被破坏吗?有人提到pobjectMember会被解构但是没有任何东西可以用于指针的破坏过程吗?是不是?

来自§15.2/ 1:

  

当控件从抛出异常的位置传递到处理程序时,将为输入try块后构造的所有自动对象调用析构函数。自动对象按照完成构造的相反顺序销毁。

这意味着在Object的构造函数中,当您抛出异常时,objectMemberpobjectMember都将被释放,动态分配的资源pobjectMember的{​​{1}}将不会被释放(这也是people recommend to use smart pointers)的原因。


  

问题3:通过调用delete auto?

来释放为新Object分配的内存

通过调用delete auto我不知道你的意思,但确保不发生内存泄漏的最简单方法是使用智能指针:

class Object {
public:

    Object()
        : objectMember(10)
        , pobjectMember(new ObjectMember(20))
        { throw 1; }

    ~Object():objectMember(10) {
        pobjectMember.reset(new ObjectMember(20));
        throw 1;
    }

private:
    ObjectMember objectMember;
    std::unique_ptr<ObjectMember> pobjectMember;
};

答案 1 :(得分:0)

  

Q1:成员:objectMember将被破坏。它是由异常展开还是其他机制引起的?

堆栈展开是指自动(局部)变量的破坏,因为控件向外和向外传递,直到找到可以处理异常的catch块。在此示例中,objectmemberpobjectmember的销毁不是堆栈展开的一部分。还有一个规则,如果异常从构造函数或析构函数传播出来,那么所有完全构造的“子对象”(包括成员和基类)都将被销毁。这就是这里发生的事情。在输入构造函数的主体之前初始化objectmemberpobjectmember,因此在抛出异常时必须销毁它们。

  

Q2:成员pobjectMember也会被破坏吗?有人提到pobjectMember会被解构但是没有任何东西可以用于指针的破坏过程吗?是不是?

我认为他们的意思(他们是对的)是,是的,pobjectmember也被销毁,但指针对象的破坏不会delete指针,所以发生内存泄漏。

请注意,Object的析构函数永远不会被调用。如果一个对象的构造函数通过退出,那么该对象永远不会真正创建,因此它也不会被破坏。

答案 2 :(得分:-1)

  

Q1:会员objectMember将被破坏。它是由异常展开引起的

  

或其他机制?

没有

  

Q2:成员pobjectMember也会被破坏吗?

没有

  

有人提到pobject会被解构,但没有为指针的破坏过程做任何事情吗?

没有。 '某人'错了,或者很困惑。 pobjectMember的空间将与包含对象的其余部分一起释放。将其称为“解构”是不正确的。除非您对其进行编码,否则pobjectMember所指向的对象不会发生任何特定情况。

  

是吗?

没有

我想知道为什么你在第一时间写这样的代码。一切都是错的,尤其是析构函数完全是胡说八道。它应该是这样的:

class Object {
public:
    Object()
    : objectMember(10),
      pobjectMember(new ObjectMember(20)) {
        throw 1;
    }

    ~Object() {
        delete pobjectMember;
        throw 1;
    }

private:
    ObjectMember objectMember ;
    ObjectMember *pobjectMember ;
}

从析构函数中抛出异常是不好的做法。在这种情况下,它实际上是非法的,因为构造函数已经抛出一个异常,所以你得到了一个非法抛出的抛出。