隐式移动构造函数应为否,除非可能
Implicit move constructor shall be noexcept if possible
基本上按照标准:
继承构造函数 (12.9( 和隐式声明的特殊成员函数(子句 12(具有异常规范。如果
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
不是 nothrow move 可构造函数1,因此Foo
的隐式移动构造函数也不是。
1Const 右值无法绑定到非常量右值引用,因此不会使用移动构造函数。相反,使用复制构造函数,并且可能会抛出std::string
的复制构造函数。
相关文章:
- 为什么不调用移动构造函数?(默认情况下只有构造器,没有别的)
- std::vector::p ush_back() 不会在 MSVC 上编译具有已删除移动构造函数的对象
- 仅包含可移动 std::map 的类的移动构造函数不起作用
- 为什么调用复制构造函数而不是移动构造函数?
- 基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 移动构造函数和右值引用
- 为什么 std::memmove 中联合的默认非平凡移动构造函数C++?
- 具有专用化的模板类中的可靠条件复制和移动构造函数
- C++:为什么不调用移动构造函数?
- 移动构造函数永远不会被调用
- C++:关于使用 Stroustrup 示例移动构造函数/赋值的问题
- 运算符+ 的规范实现涉及额外的移动构造函数
- C ++为什么在移动构造函数中需要移动/前进
- 为什么在删除"移动构造函数"时使用"复制构造函数"?
- 为什么这里不调用移动构造函数?
- 隐式移动构造函数
- 如何为具有私有成员的派生类实现移动构造函数
- 为什么不调用移动构造函数
- 是否可以避免在以下代码中复制/移动构造函数的需要?