2

Let's say we have some class with a constructor:

class MyClass
{
public:
    MyClass()
    {
    //our code goes here
    throw "OMG";//well, some code that throws an exception
    }
};

Now, when an exception occurs, stack unwinding is being performed. I also know that if the exception is thrown from the constructor, the corresponding object's destructor will not be called, because the object was never completely "created" in the first place.

I'm a little confused by this. To me that implies that the object is considered "created" only when the constructor finishes. But obviously, all the memory is allocated at some place before (or right after) the constructor is called, because we can manipulate the object's members inside the constructor.

So when exactly is the object created in memory, and what happens to the memory of an object that caused the exception?

4

3 回答 3

2

内存分配对象构造在 C++ 中是两个独立的东西。编译器只是确保当它们一起被调用时(这是常规的 -​​ 即非放置 -new运算符的情况)并且构造失败,分配被恢复。

此外,当类具有子对象(基类和/或字段)时,编译器以固定顺序调用它们的构造函数,并确保当其中一个抛出时,已经构造的子对象被正确处理(即,调用它们的析构函数)。

于 2012-08-23T08:22:55.593 回答
2

内存分配在构造函数的主体之前。

如果构造函数失败,则会释放自动分配的内存。

而“自动分配”的口音很重要——如果你在构造函数中动态分配了内存,而构造函数失败了(比如你之前可能用过newthrow "OMG",这块内存就会泄漏。

那是因为 - 你已经分配了这个内存,你需要释放它。

你是对的,没有调用析构函数,但析构函数不是释放内存的析构函数,它分配给类的自动成员。
它(基本上)用于释放由用户(在构造函数或其他地方)分配的内存。


换句话说,为对象分配内存不同于对象的构造。

另一个例子 - 如果你动态创建一个对象,比如:

MyObj* = new MyObj;

这将:

  • 称呼operator new
  • 然后调用构造函数MyObj

看,两者都不一样。

于 2012-08-23T08:23:32.177 回答
1

对象的内存被释放,但不调用析构函数(因此,例如,如果您没有正确处理构造函数中的异常,则不会释放在构造函数中创建的动态分配的指针)。在 C++11 中,规范说当且仅当一个构造函数完全完成时才调用析构函数(相关,因为构造函数可以引用另一个构造函数)。

示例(未释放由 new int () 分配的内存):

struct Broken {
   int * i;
   Broken () {
      i = new int {5};
      OperationCausingException ();
   }

   ~Broken {
      delete i;
   }
}

try {
   Broken * b = new Broken {};
} catch (...) {
}
// memory leak: *b is freed, but b->i still exists
于 2012-08-23T08:21:22.507 回答