3

我有一个类的析构函数是noexcept(false). 我知道它只在某些情况下抛出,我想将它用作带有noexcept析构函数的类的成员变量。从https://en.cppreference.com/w/cpp/language/function-try-block我读到“从函数体中的任何语句或(对于构造函数)从任何成员或基本构造函数引发的每个异常,或(对于析构函数)来自任何成员或基本析构函数,将控制权转移到处理程序序列,就像在常规 try 块中抛出的异常一样。” 这让我认为这应该是正确的:

#include <exception>

class ConditionallyThrowingDtor {
public:
    bool willThrow = true;
    ConditionallyThrowingDtor() = default;
    ~ConditionallyThrowingDtor() noexcept(false) {
        if (willThrow) {
            throw std::exception();
        }
    }
};


class NonThrowingDtor {
public:
    ConditionallyThrowingDtor x;
    ~NonThrowingDtor() noexcept try {
        x.willThrow = false;
    } catch (...) { 
        // Ignore because we know it will never happen.
    }
};


int main() {
    // ConditionallyThrowingDtor y; // Throws on destruction as expected.
    NonThrowingDtor x;
}

https://godbolt.org/z/ez17fx (MSVC)

我对noexcept功能尝试块的理解~NonThrowingDtor()noexcept保证它不会抛出(并且它通过基本上做try { ... } catch (...) { std::terminate(); } https://en.cppreference.com/w/cpp/language/noexcept_spec来做到这一点。但是功能- try-block with catch (...)and no additional throw 应该保证它永远不会抛出. Clang 对此没问题,但正如 godbolt 链接所示,MSVC 说

<source>(23): warning C4297: 'NonThrowingDtor::~NonThrowingDtor': function assumed not to throw an exception but does
<source>(23): note: destructor or deallocator has a (possibly implicit) non-throwing exception specification
4

1 回答 1

2
~NonThrowingDtor() noexcept try {
        x.willThrow = false;
    } catch (...) { 
        // Ignore because we know it will never happen.
    }

是“错误的”,等同于

~NonThrowingDtor() noexcept try {
        x.willThrow = false;
    } catch (...) {
        throw;
    }

如此简单

~NonThrowingDtor() noexcept
{
    x.willThrow = false;
}

要不传播异常,您必须显式使用return

~NonThrowingDtor() noexcept try {
        x.willThrow = false;
    } catch (...) { 
        return; // Required to not propagate exception.
    }

不幸的是,msvc 仍然会以这种不抛出的形式发出警告。
(另一方面,在这种情况下,clang/gcc 不会警告隐式(但会发出显式警告throw)。

于 2020-11-09T19:01:31.000 回答