c++ - 如果可能,隐式移动构造函数应为 noexcept

标签 c++ move-constructor noexcept

基本按标准:

An inheriting constructor (12.9) and an implicitly declared special member function (Clause 12) have an exception-specification. If f is an inheriting constructor or an implicitly declared default constructor, copy constructor, move constructor, destructor, copy assignment operator, or move assignment operator, its implicit exception-specification specifies the type-id T if and only if T is allowed by the exception-specification of a function directly invoked by f’s implicit definition; f allows all exceptions if any function it directly invokes allows all exceptions, and f has the exception-specification noexcept(true) if every function it directly invokes allows no exceptions.

因此,以下代码片段应具有隐式 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

我有什么遗漏吗?

最佳答案

Is there something I am missing?

是的。 常量

成员Foo::stringField不是std::string,它是const std::stringconst std::string 不是 nothrow move 构造函数1,因此 Foo 的隐式 move 构造函数也不是。

1 const rvalue 不能绑定(bind)到非 const rvalue 引用,因此将不会使用 move 构造函数。相反,使用了复制构造函数,并且 std::string 的复制构造函数可能会抛出。

关于c++ - 如果可能,隐式移动构造函数应为 noexcept,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61730423/

相关文章:

c++ - 为什么这个 C++0x 程序会产生意外的输出?

c++ - 根据模板参数将函数标记为 noexcept

c++ - 依赖隐式声明的 move 构造函数是否安全?

c++ - 使用指针 vector 实现移动构造函数

c++ - 在 std::Optional 的 noexcept 说明符中引用initializer_list

c++ - 如何根据 is_nothrow_move_constructible<T> 声明包装类型 X<T> noexcept 的移动构造函数?

c++ - Qt QString 十六进制值到 QByteArray

c++ - 理解 C++ 类中的 std::bad_alloc

c++ - 是否可以将类型作为函数中的参数?

c++ - 更改sublime text的默认输入源