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分配的内存任何官方文章都讨论过这个问题?
答案 0 :(得分:0)
Q1:成员:objectMember将被破坏。它是由异常展开还是其他机制引起的?
截至§15.2/ 3:
为从try块到抛出异常的路径构造的自动对象调用析构函数的过程称为“堆栈展开”。如果在堆栈展开期间调用的析构函数以异常退出,则std :: terminate被称为(15.5.1)。 [注意:因此析构函数通常应该捕获异常,而不是让它们从析构函数中传播出来。
所以,是的,这就是它的召唤方式。
Q2:成员pobjectMember也会被破坏吗?有人提到pobjectMember会被解构但是没有任何东西可以用于指针的破坏过程吗?是不是?
来自§15.2/ 1:
当控件从抛出异常的位置传递到处理程序时,将为输入try块后构造的所有自动对象调用析构函数。自动对象按照完成构造的相反顺序销毁。
这意味着在Object
的构造函数中,当您抛出异常时,objectMember
和pobjectMember
都将被释放,但动态分配的资源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
块。在此示例中,objectmember
和pobjectmember
的销毁不是堆栈展开的一部分。还有一个规则,如果异常从构造函数或析构函数传播出来,那么所有完全构造的“子对象”(包括成员和基类)都将被销毁。这就是这里发生的事情。在输入构造函数的主体之前初始化objectmember
和pobjectmember
,因此在抛出异常时必须销毁它们。
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 ;
}
从析构函数中抛出异常是不好的做法。在这种情况下,它实际上是非法的,因为构造函数已经抛出一个异常,所以你得到了一个非法抛出的抛出。