加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 强制执行明确默认的特殊成员函数生成

发布时间:2020-12-14 19:20:15 所属栏目:百科 来源:网络整理
导读:在C 11中,如果自动阻止了隐式生成,则可以显式地默认特殊成员函数. 但是,显式默认默认特殊成员函数只会撤消由于手动声明某些其他特殊成员函数(复制操作,析构函数等)而导致的隐式删除,它不会强制编译器生成函数,并且代码被认为是即使实际上不能生成函数,也要很
在C 11中,如果自动阻止了隐式生成,则可以显式地默认特殊成员函数.

但是,显式默认默认特殊成员函数只会撤消由于手动声明某些其他特殊成员函数(复制操作,析构函数等)而导致的隐式删除,它不会强制编译器生成函数,并且代码被认为是即使实际上不能生成函数,也要很好地形成.

请考虑以下情形:

struct A
{
    A ()         = default;
    A (const A&) = default;
    A (A&&)      = delete;  // Move constructor is deleted here
};

struct B
{
    B ()         = default;
    B (const B&) = default;
    B (B&&)      = default; // Move constructor is defaulted here

    A a;
};

B中的移动构造函数不会由编译器生成,因为这样做会导致编译错误(删除A的移动构造函数).在没有明确删除A的构造函数的情况下,B的移动构造函数将按预期生成(复制A,而不是移动它).

试图移动这样的对象将默默使用复制构造函数:

B b;
B b2 (std::move(b)); // Will call B's copy constructor

有没有办法强制编译器生成函数或发出编译错误,如果它不能?如果没有这种保证,如果单个已删除的构造函数可以禁用整个对象层次结构的移动,则很难依赖默认的移动构造函数.

解决方法

有一种方法可以检测类似A的类型.但只有在类型显式删除移动构造函数时.如果将移动构造函数隐式生成为已删除,则它将不参与重载解析.这就是为什么B可以移动,即使A不是. B默认移动构造函数,这意味着它被隐式删除,因此复制发生.

因此,B是可构造的.但是,A不是.所以这是一个简单的问题:

struct B
{
    static_assert(is_move_constructible<A>::value,"Oops...");

    B ()         = default;
    B (const B&) = default;
    B (B&&)      = default; // Move constructor is defaulted here

    A a;
};

现在,没有一般方法可以使任何包含只复制类型的类型执行您想要的操作.也就是说,您必须单独对每种类型进行静态断言;你不能在默认移动构造函数中放置一些语法来尝试移动B失败.

其原因部分在于向后兼容性.想想所有声明用户定义的拷贝构造函数的前C 11代码.根据C 11中移动构造函数生成的规则,所有这些都将删除移动构造函数.这意味着任何形式的代码T t = FuncReturningTByValue();即使它通过调用复制构造函数在C 98/03中工作正常也会失败.因此,如果无法生成移动构造函数,则通过复制而不是移动来解决此问题.

但是因为= default意味着“做你通常会做的事情”,它还包括这种特殊的重载解析行为,它忽略了隐式删除的移动构造函数.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读