首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么派生类move是可构造的,而基类不是?

为什么派生类move是可构造的,而基类不是?
EN

Stack Overflow用户
提问于 2016-08-25 15:23:29
回答 2查看 2.4K关注 0票数 57

考虑以下示例:

代码语言:javascript
复制
#include <iostream>
#include <string>
#include <utility>

template <typename Base> struct Foo : public Base {
    using Base::Base;
};

struct Bar {
    Bar(const Bar&) { }
    Bar(Bar&&) = delete;
};

int main() {
    std::cout << std::is_move_constructible<Bar>::value << std::endl; // NO
    std::cout << std::is_move_constructible<Foo<Bar>>::value << std::endl; // YES. Why?!
}

为什么编译器会生成一个移动构造函数,尽管基类是不可移动构造的?

这是在标准中还是在编译器错误中?有可能“完美地传播”将结构从基类移动到派生类吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-08-25 15:30:53

因为:

定义为已删除的默认移动构造函数将被重载解析忽略。

(class.copy/11)

Bar的move构造函数已显式删除,因此无法移动Bar。但Foo<Bar>的move构造函数在被隐式声明为默认成员后被隐式删除,原因是Bar成员无法移动。因此,可以使用其复制构造函数移动Foo<Bar>

编辑:我还忘记提到一个重要事实,即继承构造函数声明(如using Base::Base )不继承默认、复制或移动构造函数,这就是为什么Foo<Bar>没有从Bar继承显式删除的移动构造函数的原因。

票数 30
EN

Stack Overflow用户

发布于 2016-08-25 15:29:41

1. std::is_move_constructible的行为

这是std::is_move_constructible的预期行为

这意味着使用复制构造函数,仍然可以从右值引用T&&构造T。而且Foo<Bar>有一个Implicitly-declared copy constructor

2. Foo<Bar>的隐式声明的构造函数

为什么编译器会生成移动构造函数,尽管基类是不可移动构造的?

..。

3. Bar Foo<Bar>之间的不同行为

重点在于,重载解析会忽略已删除的隐式声明的move构造函数,这使得使用其构造函数移动构造Foo<Bar>成为可能。但是显式删除的move构造器将参与重载解决,这意味着当尝试移动构造器Bar时,删除的move构造器将被选中,那么程序是错误的。

这就是为什么Foo<Bar>是可移动构造的,而Bar不是。

该标准对此有明确的声明。$12.8/11 Copying and moving class objects [class.copy]

定义为已删除的默认移动构造函数将被重载解析忽略(over.match,over.over)。注意:删除的move构造函数会干扰来自r值的初始化,而右值可以使用复制构造函数。-结束注释

票数 26
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39139087

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档