cppreference.com 中关于析构函数的隐式抛出的引述是错字吗?
Is this quote from cppreference.com about implicit throw from a destructor a typo?
https://en.cppreference.com/w/cpp/language/function-try-block 中的这句话有错字吗?
Reaching the end of a catch clause for a function-try-block on a destructor also automatically rethrows the current exception as if by throw;
, but a return statement is allowed.
似乎很难相信析构函数会自动重新抛出,因为我读过的每一位专家的每篇文章都说析构函数在任何情况下都不应该抛出。事实上,引号上方的示例代码显示了构造函数而非析构函数的隐式抛出。
因此,我想知道,该陈述是否错误,应该指出构造函数的行为?
当我开始考虑这个问题时,我一直在查看另一篇 Whosebug 文章:。它已经有了答案,但没有人首先质疑报价是否准确。
答案是否定的,这不是错别字。
cppreference文章没有给出析构函数try块的例子,所以我自己制作了一个并进行了测试。下面是相同的代码。我使用 v142 平台工具集和 C++20 方言使用 Microsoft VS2019 进行了测试。
如果你执行这个,会调用一个abort,这与编译器发出的警告是一致的。这表明函数 catch 块会自动执行 re-throw,即使对于析构函数也是如此。如果您取消注释 return
语句,它不会抛出。虽然,我发现它是 counter-intuitive,但编写 return
语句提供了一种防止隐式抛出的解决方法,正如引用的 Whosebug 文章所建议的那样。
#include <iostream>
#include <string>
struct S
{
std::string m;
S(const std::string& str, int idx) try : m(str, idx)
{
std::cout << "S(" << str << ", " << idx << ") constructed, m = " << m << '\n';
}
catch (const std::exception& e)
{
std::cout << "S(" << str << ", " << idx << ") failed: " << e.what() << '\n';
} // implicit "throw;" here
~S() try
{
if (m.length() > 5) {
throw std::exception("shouldn't have been that big!");
}
std::cout << "destroyed!" << std::endl;
}
catch (const std::exception& e)
{
//return;
}
};
int main()
{
S s1{ "ABC", 1 }; // does not throw (index is in bounds)
try
{
S s2{ "ABC", 4 }; // throws (out of bounds)
}
catch (std::exception& e)
{
std::cout << "S s2... raised an exception: " << e.what() << '\n';
}
try
{
S s3("123456", 0);
}
catch (std::exception& e)
{
std::cout << "S s2... raised an exception: " << e.what() << '\n';
}
}
https://en.cppreference.com/w/cpp/language/function-try-block 中的这句话有错字吗?
Reaching the end of a catch clause for a function-try-block on a destructor also automatically rethrows the current exception as if by
throw;
, but a return statement is allowed.
似乎很难相信析构函数会自动重新抛出,因为我读过的每一位专家的每篇文章都说析构函数在任何情况下都不应该抛出。事实上,引号上方的示例代码显示了构造函数而非析构函数的隐式抛出。
因此,我想知道,该陈述是否错误,应该指出构造函数的行为?
当我开始考虑这个问题时,我一直在查看另一篇 Whosebug 文章:
答案是否定的,这不是错别字。
cppreference文章没有给出析构函数try块的例子,所以我自己制作了一个并进行了测试。下面是相同的代码。我使用 v142 平台工具集和 C++20 方言使用 Microsoft VS2019 进行了测试。
如果你执行这个,会调用一个abort,这与编译器发出的警告是一致的。这表明函数 catch 块会自动执行 re-throw,即使对于析构函数也是如此。如果您取消注释 return
语句,它不会抛出。虽然,我发现它是 counter-intuitive,但编写 return
语句提供了一种防止隐式抛出的解决方法,正如引用的 Whosebug 文章所建议的那样。
#include <iostream>
#include <string>
struct S
{
std::string m;
S(const std::string& str, int idx) try : m(str, idx)
{
std::cout << "S(" << str << ", " << idx << ") constructed, m = " << m << '\n';
}
catch (const std::exception& e)
{
std::cout << "S(" << str << ", " << idx << ") failed: " << e.what() << '\n';
} // implicit "throw;" here
~S() try
{
if (m.length() > 5) {
throw std::exception("shouldn't have been that big!");
}
std::cout << "destroyed!" << std::endl;
}
catch (const std::exception& e)
{
//return;
}
};
int main()
{
S s1{ "ABC", 1 }; // does not throw (index is in bounds)
try
{
S s2{ "ABC", 4 }; // throws (out of bounds)
}
catch (std::exception& e)
{
std::cout << "S s2... raised an exception: " << e.what() << '\n';
}
try
{
S s3("123456", 0);
}
catch (std::exception& e)
{
std::cout << "S s2... raised an exception: " << e.what() << '\n';
}
}