物体究竟在什么时候"created"?
At what moment is an object exactly "created"?
假设我们有一个带有构造函数的类:
class MyClass
{
public:
MyClass()
{
//our code goes here
throw "OMG";//well, some code that throws an exception
}
};
现在,当发生异常时,正在执行堆栈展开。我还知道,如果从构造函数抛出异常,则不会调用相应对象的析构函数,因为该对象最初从未完全"创建"。
我对此有点困惑。对我来说,这意味着只有当构造函数完成时,对象才被认为是"创建的"。但很明显,所有内存都是在调用构造函数之前(或之后)的某个位置分配的,因为我们可以在构造函数中操作对象的成员。
那么,对象究竟是什么时候在内存中创建的,导致异常的对象的内存会发生什么?
内存是在构造函数主体之前分配的。
如果构造函数失败,则自动分配的内存将被释放。
"自动分配"的重音很重要——如果你在构造函数中动态分配了内存,而构造函数失败了(例如,你可能在throw "OMG"
之前使用了new
),那么这个内存就会泄漏
那是因为-你已经分配了这个内存,你需要释放它。
你是对的,没有调用析构函数,但析构函数不是释放内存的那个,分配给类的auto成员
它(基本上)用于释放内存,由用户(在构造函数或其他地方)分配
换句话说,为对象分配内存与对象的构造不同。
另一个例子——如果你动态地创建一个对象,比如:
MyObj* = new MyObj;
这将:
- 呼叫
operator new
- 然后调用
MyObj
的构造函数
看,这两件事不一样。
内存分配和对象构造是C++中两个独立的东西。编译器只是确保当它们一起被调用时(这是正则(即非放置)new
运算符的情况)并且构造失败时,分配会被恢复。
此外,当类具有子对象(基类和/或字段)时,编译器会按固定顺序调用它们的构造函数,并确保其中一个抛出时,已经构建的子对象得到正确处理(即,调用它们的析构函数)。
对象的内存被释放,但析构函数没有被调用(因此,例如,如果您没有正确处理构造函数中的异常,则在构造函数中创建的动态分配指针不会被释放)。在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
- 什么时候调用组成单元对象的析构函数
- 什么时候在C++中返回常量引用是个好主意
- 什么时候调用析构函数
- boost odeint什么时候真正调用观测者
- 编译器对数组声明大小的计算。什么时候发生?
- 什么时候最好在子进程中使用 CPU 或 I/O 密集型代码 [ C++ ]
- 您应该在什么时候创建自己的异常类型
- 我什么时候会默认(而不是删除)基类中的复制和移动操作
- 什么时候可以使用常量装饰调用我的重载函数?
- unordered_map什么时候返回 -1?
- QCoreApplication什么时候有效?
- sizeof(size_t) 和 sizeof(ptrdiff_t) 什么时候会有所不同?
- 什么时候用指针调用C++类构造函数
- 我不明白在这个例子中什么时候调用构造函数
- 如果真的需要std::move,我们应该什么时候声明右值refs
- P1008("prohibit aggregates with user-declared constructors")在实践中什么时候有用?
- 程序什么时候会创建多个堆
- 调用boost.asio的异步函数时,线程是什么时候创建的
- Swig/python : 什么时候需要 SWIG_init() ?
- 物体究竟在什么时候"created"?