是在委托构造函数抛出时自动回收的内存
Is the memory automatically reclaimed when a delegating constructor throws?
接下来是:当委托构造函数抛出时,是否调用析构函数?
class X
{
public:
X() {};
X(int) : X() { throw std::exception(); }
X(double) { throw std::exception(); }
~X();
};
动态内存呢?通常,构造函数中的异常意味着对象没有完全构造,因此内存是干净的,不会丢失。
但上一个问题中的论点是,在委托完成后,对象被完全构造(或完全初始化)。这对回收内存有何影响?我希望记忆还是干净的!
int main()
{
new X(5); // new called
// delete called because delegate completed.
// I assume:
// Memory re-claimed (because constructor did not complete)
// I assume the C++11 standard adjusted to compensate.
// As a constructor did complete.
}
也比较:
int main()
{
new X(5.0); // new called
// Delete **NOT** called
// Memory re-claimed (because constructor did not complete)
}
如果内存已清理,则需要从C++03规范更改内存何时清理的定义。行为是如何改变的?
如果new
调用的构造函数抛出异常,则new
分配的内存将自动解除分配。委派构造函数在这方面没有任何改变。
如果上述对象初始化的任何部分76通过抛出异常而终止,并且可以找到合适的解除分配函数,则调用解除分配函数来释放正在构建对象的存储器
--C++11[expr.new]5.3.4/18
所描述的"对象初始化的任何部分"包括构造函数调用和传递给构造函数的表达式的求值。
此外,这种行为在C++98标准[C++98 5.4.3/17]中有相同的规定。委托构造函数的唯一区别是,你的心理模型以前是否基于正在完全构建的对象。给定的委托构造函数不再等同于何时发生解除分配的实际规范。
在你的第一个例子中:
new X(5);
事件顺序为:
- 调用了分配函数
- 调用了X(int)
- 调用了X()(并成功退出)
- X(int)引发异常
- ~X()已调用
- X(int)通过异常退出
- 由于对象初始化失败,调用了解除分配函数
- 异常继续正常传播
对于第二个示例
new X(5.0);
- 调用了分配函数
- X(双)调用
- X(double)失败并出现异常
- 由于对象初始化失败,调用了解除分配函数
- 异常继续正常传播
您可以通过替换分配和解除分配函数来观察这种行为:
#include <iostream>
#include <cstdlib>
#include <stdexcept>
#include <new>
void *operator new(std::size_t s) {
if (void *ptr = std::malloc(s)) {
std::cout << "allocationn";
return ptr;
}
throw std::bad_alloc{};
}
void operator delete(void *ptr) noexcept {
if (ptr) {
std::cout << "deallocationn";
std::free(ptr);
}
}
struct S {
S() {};
S(int) : S{} { throw std::exception(); }
S(double) { throw std::exception(); }
~S() { std::cout << "destructorn"; }
};
int main() {
std::cout << "test 1n";
try {
new S(1);
} catch(...) {
std::cout << "exception caughtn";
}
std::cout << "test 2n";
try {
new S(1.);
} catch(...) {
std::cout << "exception caughtn";
}
}
该程序的正确输出为:
test 1
allocation
destructor
deallocation
exception caught
test 2
allocation
deallocation
exception caught
相关文章:
- 从构造函数抛出异常时如何克服内存泄漏
- 如何为 std::vector 分配内存,然后稍后为某些元素调用构造函数?
- 在构造函数中分配内存失败是如何冒泡的
- 动态分配的内存构造函数
- 构造函数主体内的本地指针C++内存泄漏
- 从构造函数内存泄漏引发异常
- QThreads - 为什么要在构造函数中分配内存而不是使用普通的类成员?
- 构造函数对象赋值是否泄漏内存
- 如何使用构造函数初始化内存地址(指针变量)?
- 是否可以反序列化(从原始内存块)没有默认构造函数的对象?
- 在使用新操作员和C 中的结构的调用构造函数时,获得内存损坏(Malloc)
- 如果在构造函数中发生异常,如何释放动态内存
- 在类构造函数中初始化映射时,如何避免内存泄漏
- 链接列表C 的复制构造函数中的内存泄漏
- 复制赋值构造函数中的aligned_alloc内存块在释放时崩溃
- 构造函数中的动态内存分配
- 构造函数和内存泄漏中的异常
- 当构造函数引发异常时,如何在构造函数中分配内存
- 构造函数C++中的类实例内存地址
- C 内存模型是否提供了有关构造函数操作的保证