为什么隐式删除移动构造函数调用复制构造函数?

时间:2015-11-05 08:46:20

标签: c++11 constructor move

隐式删除的移动构造函数(C的移动)看起来像非声明的移动和编译器尝试使用复制构造函数(C的副本)。

为什么隐式删除的移动(C移动)和显式删除移动(B的移动)之间存在差异

有一些解释,还有更多细节吗?

Why is the move constructor neither declared nor deleted with clang?

@dyp评论:

  

因为未声明隐式删除的移动构造函数

并链接到DR1402:

http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1402

  

重载解析(13.3 [over.match])忽略定义为已删除的默认移动构造函数。 [注意:删除的移动构造函数否则会干扰rvalue的初始化,而rvalue可以使用复制构造函数。 - 后注]

http://en.cppreference.com/w/cpp/language/move_constructor

  

(自C ++ 14开始)重载解析会忽略已删除的隐式声明的移动构造函数(否则会阻止rvalue的复制初始化)

示例代码:

#include <utility>

class A {
public:
    A() = default;
    A(const A&) = delete;
    A(A&&) = delete;
};

class B : public A {
public:
    B() = default;
    B(const B&) = delete;
    B(B&&) = delete; // explicitly deleted move
};

class C: public A {
public:
    C() = default;
    C(const C&) = default; // implicitly deleted copy because A's copy is deleted
    C(C&&) = default; // implicitly deleted move because A's move is deleted
};

int main() {
    A a1;
    A a2(std::move(a1)); // error, A's move is explicitly deleted

    B b1;
    B b2(std::move(b1)); // error, B's move is explicitly deleted

    C c1;
    C c2(std::move(c1)); // error, C's **copy** is implicitly deleted

    return 0;
}

编译器消息:

Apple LLVM version 7.0.0 (clang-700.1.76)
clang++ -std=c++11 3.cpp

3.cpp:26:7: error: call to deleted constructor of 'A'
    A a2(std::move(a1)); // error, A's move is explicited deleted
      ^  ~~~~~~~~~~~~~
3.cpp:7:5: note: 'A' has been explicitly marked deleted here
    A(A&&) = delete;
    ^
3.cpp:29:7: error: call to deleted constructor of 'B'
    B b2(std::move(b1)); // error, B's move is explicited deleted
      ^  ~~~~~~~~~~~~~
3.cpp:14:5: note: 'B' has been explicitly marked deleted here
    B(B&&) = delete; // explicitly deleted move
    ^
3.cpp:32:7: error: call to implicitly-deleted copy constructor of 'C'
    C c2(std::move(c1)); // error, C's **copy** is implicited deleted
      ^  ~~~~~~~~~~~~~
3.cpp:20:5: note: explicitly defaulted function was implicitly deleted here
    C(const C&) = default; // implicitly deleted copy
    ^
3.cpp:17:10: note: copy constructor of 'C' is implicitly deleted because base class 'A' has a deleted copy constructor
class C: public A {
         ^
3.cpp:6:5: note: 'A' has been explicitly marked deleted here
    A(const A&) = delete;
    ^
3 errors generated.

1 个答案:

答案 0 :(得分:0)

std :: move不一定强制移动,它只是将参数转换为xvalue,以便在可能的情况下移动 。它可以被忽略,并且大多数时候不需要调用std :: move来使编译器移动,甚至更好地完全优化副本。

http://en.cppreference.com/w/cpp/utility/move

  

它完全等同于static_cast到rvalue引用类型。

static_cast<typename std::remove_reference<T>::type&&>(t)