C++为什么我不能在具有已删除的默认构造函数的对象上使用swap

Mak*_*tro 4 c++ rvalue default-constructor move-constructor move-semantics

我正在尝试为使用类Id的对象A实现移动构造函数.类Id是自动生成的,为了将来的编码健全,我选择在我这样做时删除默认构造函数.

然而,当我尝试在A的移动构造函数中使用swap时,它抱怨Id默认构造函数被删除.我认为交换不是构造任何新对象,而只是交换两个项目的地址.

我是否误解了它,它实际上是在创建第三个临时实例?

如果是这种情况,下面实现移动构造函数的最佳方法是什么?

我在下面列出了一个最小的例子:

class Id {

public:
    Id() = delete;
    Id(std::string id) : m_id(id) {}

private:
    std::string m_id;
};

class A {

public:
    A() = delete;
    A(Id id) : m_id(id) {}


    A(A&& other) {
        std::swap(m_id, other.m_id);
    }

private:
    Id m_id;
};
Run Code Online (Sandbox Code Playgroud)

编译器返回以下错误:

In constructor 'A::A(A&&)':
21:18: error: use of deleted function 'Id::Id()'
8:5: note: declared here
In file included from /usr/include/c++/4.9/bits/stl_pair.h:59:0,
                 from /usr/include/c++/4.9/bits/stl_algobase.h:64,
                 from /usr/include/c++/4.9/bits/char_traits.h:39,
                 from /usr/include/c++/4.9/ios:40,
                 from /usr/include/c++/4.9/ostream:38,
                 from /usr/include/c++/4.9/iostream:39,
                 from 2:
/usr/include/c++/4.9/bits/move.h: In instantiation of 'void std::swap(_Tp&, _Tp&) [with _Tp = A]':
34:17:   required from here
/usr/include/c++/4.9/bits/move.h:176:11: error: use of deleted function 'A& A::operator=(const A&)'
       __a = _GLIBCXX_MOVE(__b);
           ^
15:7: note: 'A& A::operator=(const A&)' is implicitly declared as deleted because 'A' declares a move constructor or move assignment operator
In file included from /usr/include/c++/4.9/bits/stl_pair.h:59:0,
                 from /usr/include/c++/4.9/bits/stl_algobase.h:64,
                 from /usr/include/c++/4.9/bits/char_traits.h:39,
                 from /usr/include/c++/4.9/ios:40,
                 from /usr/include/c++/4.9/ostream:38,
                 from /usr/include/c++/4.9/iostream:39,
                 from 2:
/usr/include/c++/4.9/bits/move.h:177:11: error: use of deleted function 'A& A::operator=(const A&)'
       __b = _GLIBCXX_MOVE(__tmp);
Run Code Online (Sandbox Code Playgroud)

Bo *_*son 6

可以swapId对象上使用,问题不在那里,而是在构造函数中A.

A(A&& other) {
    std::swap(m_id, other.m_id);
}
Run Code Online (Sandbox Code Playgroud)

这是默认构造一个Id,然后与另一个成员交换它A.

要避免使用默认构造函数,必须Id在初始化列表中初始化

A(A&& other) : m_id(std::move(other.m_id))
{  }
Run Code Online (Sandbox Code Playgroud)