c++ - 如果可能,隐式移动构造函数应为 noexcept
问题描述
基本上按照标准:
继承构造函数 (12.9) 和隐式声明的特殊成员函数 (Clause 12) 具有异常规范。If
f
是继承构造函数或隐式声明的默认构造函数、复制构造函数、移动构造函数、析构函数、复制赋值运算符或移动赋值运算符,其隐式异常规范指定类型 IDT
当且仅当异常规范T
允许 由的隐式定义直接调用的函数;如果它直接调用的任何函数允许所有异常,并且具有异常规范,则允许所有异常f
f
f
noexcept(true)
如果它直接调用的每个函数都不允许例外。
因此,以下代码片段应具有隐式noexcept移动构造函数:
template<typename _Tp>
class Foo
{
public:
Foo() = default;
explicit Foo(const std::string& s, const std::function<bool(_Tp&)>& f) : stringField(s), funcField(f) {}
private:
const std::string stringField;
std::function<bool(_Tp&)> funcField;
};
但不幸的是,它没有:
int main()
{
std::cout << "std::string: " << std::is_nothrow_move_constructible_v<std::string> << std::endl;
std::cout << "std::function: " << std::is_nothrow_move_constructible_v<std::function<bool(std::string&)>> << std::endl;
std::cout << "string_t: " << std::is_nothrow_move_constructible_v<Foo<std::string>> << std::endl;
return 0;
}
印刷
std::string: 1
std::function: 1
string_t: 0
在 Ubuntu 18.04 LTS 上使用 g++ 8.3.0
有什么我想念的吗?
解决方案
有什么我想念的吗?
是的。const
成员Foo::stringField
不是std::string
,它是const std::string
。const std::string
is not nothrow move constructible 1,因此隐式 move 构造函数Foo
既不是。
1 const rvalue 不能绑定到非 const rvalue 引用,所以不会使用 move 构造函数。相反,使用了复制构造函数,std::string
并且可能会抛出复制构造函数。
推荐阅读
- c++ - 是否可以使用指针作为模板参数?
- javascript - 画布 fillText 和 fillRec 不呈现
- powershell - 是命令 Get-PnPFolderItem 的属性或字段“ServerRelativeUrl”的一部分
- javascript - 如何从子组件中获取父表单的字段?
- .htaccess - htaccess 重写多个参数
- android - 当达到设定的时间时,我的 AlarmManager 可以发出第一个警报,而不是在第一次重复之后?
- c# - 无法从 Jenkins 获得最后的构建状态 - 403 被禁止
- r - 从 R 中当前数据集中不存在的列表中创建新变量
- sql - 如何获得按城市和年份分组的最后支付金额?
- php - 如何让我最近的数据首先出现在数据库 php 中