从此:当委托构造函数抛出异常时,析构函数是否被调用? https://stackoverflow.com/q/17657761/14065
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
被自动释放。委托构造函数在这方面没有任何改变。
If any part of the object initialization described above76 terminates by throwing an exception and a suitable deallocation function can be found, the deallocation function is called to free the memory in which the object was being constructed
— C++11 [expr.new] 5.3.4/18
所描述的“对象初始化的任何部分”包括构造函数调用和传递给构造函数的表达式的求值。
此外,C++98 标准 [C++98 5.4.3/17] 中也同样指定了此行为。委托构造函数的唯一区别在于您的心智模型之前是否基于完全构造的对象。给定的委托构造函数不再等同于释放发生时间的实际规范。
在你的第一个例子中:
new X(5);
事件的顺序是:
- 称为分配函数
- X(int) 调用
-
-
-
- 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 << "allocation\n";
return ptr;
}
throw std::bad_alloc{};
}
void operator delete(void *ptr) noexcept {
if (ptr) {
std::cout << "deallocation\n";
std::free(ptr);
}
}
struct S {
S() {};
S(int) : S{} { throw std::exception(); }
S(double) { throw std::exception(); }
~S() { std::cout << "destructor\n"; }
};
int main() {
std::cout << "test 1\n";
try {
new S(1);
} catch(...) {
std::cout << "exception caught\n";
}
std::cout << "test 2\n";
try {
new S(1.);
} catch(...) {
std::cout << "exception caught\n";
}
}
该程序的正确输出是:
test 1
allocation
destructor
deallocation
exception caught
test 2
allocation
deallocation
exception caught
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)