c++ - 由函数指针初始化的 std::function 的异常安全
问题描述
的构造函数std::function
未声明noexcept
:
template< class F > function( F f );
另一方面,C++ 参考提到以下内容:
如果 f 是函数指针或 std::reference_wrapper 则不抛出,否则可能抛出 std::bad_alloc 或存储的可调用对象的复制构造函数抛出的任何异常。
这是否意味着可以安全地声明以下类的构造函数,因为我使用指向静态成员函数的指针进行了noexcept
初始化?std::function
class Worker
{
public:
Worker() noexcept {} // ok?
void test() { reporter("test"); }
private:
static void dummy(const std::string& ) {};
std::function<void (const std::string&)> reporter = &dummy; // doesn't throw an exception?
};
int main()
{
Worker w;
w.test();
}
如果std::function
member 是从 lambda 构造的,那么声明构造函数noexcept
会是错误的吗?
class Worker
{
public:
Worker() noexcept {} // bad?
void test() { reporter("Test"); }
private:
std::function<void (const std::string&)> reporter = [](const std::string& ){}; // may throw?
};
我还注意到,当声明的构造函数noexcept
默认时,GCC 会出错,因为它的异常规范与隐式异常规范不匹配,这是noexcept(false)
由于std::function
构造函数没有被声明为 noexcept。
class Worker
{
public:
Worker() noexcept = default; // this won't compile
void test() { reporter("test"); }
private:
static void dummy(const std::string& ) {};
std::function<void (const std::string&)> reporter = &dummy;
};
解决方案
这是否意味着可以安全地声明以下类的构造函数,因为我使用指向静态成员函数的指针进行了
noexcept
初始化?std::function
请注意,声明一个函数总是“安全的” noexcept
。如果抛出异常,程序将终止,但这不是未定义的行为。
但是,是的,在您的情况下,不应抛出异常,因此不应发生程序终止。标准说:“抛出:Nothing if f
is ...一个函数指针......”
如果
std::function
member 是从 lambda 构造的,那么声明构造函数noexcept
会是错误的吗?
是的,在你想要的意义上它是“错误的”(如果程序抛出,程序将终止),因为 lambda 不是函数指针。相反,在 lambda 前面加上一元operator+
,使其成为函数指针:
std::function<void (const std::string&)> reporter = +[](const std::string& ){};
我可能会在评论中提到这一点,特别是如果你没有评论为什么构造函数是noexcept
.
我还注意到,当声明的构造函数
noexcept
默认时,GCC 会出错
GCC 和 Clang 的最新版本都没有给出错误,所以如果这是真的,那可能是根据标准发布的缺陷报告。
推荐阅读
- swift - 如何处理在firestore中包含具有空值字段的文档?
- javascript - 事件循环 - 无限循环不会停止在 Chrome 中渲染管道,但会在 Firefox 上停止
- javascript - Jquery - 选择具有动态名称的数组集
- c++ - 使用 vcpkg 构建的 Zlib - 在 x86 模式下在 MSVC 2015 中链接时出错
- json - 使用反应具有相同json问题的多个页面
- wordpress - 看不到远程 WordPress 安装的内容,但站点加载
- python - 在 Django 3 中寻找基于时区的通知的更好方法
- javascript - 未找到 Laravel 6 css 和 js 文件( net::ERR_ABORTED 404 (Not Found) )
- javascript - 有没有比官方 eslint-watch 更快的 npm 包?
- php - 如何通过在php中添加多个值来修改现有cookie