gpt4 book ai didi

c++ - 委托(delegate)构造函数抛出时是否会自动回收内存?

转载 作者:IT老高 更新时间:2023-10-28 22:36:25 25 4
gpt4 key购买 nike

接下来:Is the destructor called when a delegating constructor throws?

class X
{
public:
X() {};
X(int) : X() { throw std::exception(); }
X(double) { throw std::exception(); }
~X();
};

动态内存呢?通常构造函数中的异常意味着对象没有完全构造,因此内存被清理并且没有丢失。

但是上一个问题的论点是对象在委托(delegate)完成后完全构造(或完全初始化)。这对回收内存有何影响?我希望内存仍然被清理!

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 分配的内存会自动释放。委托(delegate)构造函数在这方面没有任何改变。

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] 中同样指定了此行为。委托(delegate)构造函数的唯一区别是您的心智模型是否以前基于完全构造的对象。给定的委托(delegate)构造函数不再等同于释放发生时间的实际规范。


在你的第一个例子中:

new X(5);

事件顺序为:

  • 调用分配函数
  • X(int) 调用
    • X() 被调用(并成功退出)
    • X(int) 抛出异常
    • ~X() 调用
  • X(int) 通过异常退出
  • 由于对象初始化失败而调用了释放函数
  • 异常继续正常传播

第二个例子

new X(5.0);
  • 调用分配函数
  • X(double) 调用
  • 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

关于c++ - 委托(delegate)构造函数抛出时是否会自动回收内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17658902/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com