gpt4 book ai didi

c++ - C++11 中的作用域(失败)?

转载 作者:搜寻专家 更新时间:2023-10-31 00:00:31 24 4
gpt4 key购买 nike

我写了一个非常简单的解决方案,但是有人笑了,发现了一个缺陷,如图所示 http://ideone.com/IcWMEf

#include <iostream>
#include <ostream>
#include <functional>
#include <exception>
using namespace std;

// Wrong scope(failure)
class FailBlockT
{
typedef function<void()> T;
public:
T t;
FailBlockT(T t)
{
this->t=t;
}
~FailBlockT()
{
if (std::uncaught_exception())
{
t();
}
}
};

struct Test
{
~Test()
{
try
{
FailBlockT f([]()
{
cout << "failure" << endl;
});
// there is no any exception here, but "failure" is printed.
// See output below
}
catch(...)
{
cout << "some exception" << endl;
}
}
};

int main()
{
try
{
Test t;
throw 1;
}
catch(int){}
return 0;
}

简而言之,问题是我的代码查看 std::uncaught_exception()。当抛出异常并执行正常的析构函数时。如果我在那里使用范围故障,它将查看 std::uncaught_exception() 并认为对象范围由于异常而丢失,而不是简单地走出范围。

我想不出任何好的解决方案来区分正常离开范围与在其中抛出异常。是的,我知道在 dtors 中抛出是个坏主意,但这就是为什么我没有注意到这个问题,因为我从不抛出异常。

我该如何区分/解决这个问题?

最佳答案

No exception was thrown but it thinks it has.

异常抛出,只是不是从那里

C++11 中没有机制来询问“异常是从我下面的代码中抛出的,但不是是从调用堆栈中其他地方的代码中抛出的吗?” std::uncaught_exception 正在做它应该做的事情:说明在调用函数时当前是否有正在解决的异常。并且有,所以它返回 true

C++17增加了std::uncaught_exceptions(注意复数),可以用来检测差异。使用这样的工具,您可以使您的 FailBlock 对象工作:

template<typename Func>
class FailBlockT
{
private:
int e_count_;
T t_;

public:
FailBlockT(T t) : e_count_(std::uncaught_exceptions()), t_(t) {}

FailBlock(const FailBlock &) = delete; //The type should not be mobile.

~FailBlockT()
{
if (std::uncaught_exceptions() != e_count_)
{
t_();
}
}
};

std::uncaught_exceptions() 返回调用时引发堆栈展开的异常数。如果一个对象(假设它是一个堆栈对象)的构造函数和析构函数中的数字相同,则由于在使用此类型的地方抛出异常而未调用析构函数。

但是,如果没有这个工具,您将无法区分引发范围退出的异常和异常展开恰好正在进行时退出范围。因此,您将不得不像其他人一样硬着头皮捕获异常。

或者只是不要把这个 FailBlock 东西放在析构函数中。在我看来,那些应该直接进入实际可以抛出的常规函数​​(并且析构函数永远不应该抛出)。在我看来,您担心的是一个没有任何实际意义的极端情况。

关于c++ - C++11 中的作用域(失败)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13001792/

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